From: Cameron Gutman Date: Thu, 4 Aug 2011 17:42:50 +0000 (+0000) Subject: - Update to r53061 X-Git-Tag: backups/GSoC_2011/TcpIpDriver@60644~21 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=b1d8a4df819c95bcb81cd8d6e8d9a397125147a9;hp=8b36c2fed55e2160b52793adcf111914ded5d10a - Update to r53061 - Branch repair (part 2 of x) svn path=/branches/GSoC_2011/TcpIpDriver/; revision=53063 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index aa18faa1c23..8f1988e29c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,11 @@ else() #useful stuff! include(CMakeParseArguments) + + if(ENABLE_CCACHE) + set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF) + set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES OFF) + endif() # Do some cleanup file(REMOVE diff --git a/base/applications/CMakeLists.txt b/base/applications/CMakeLists.txt index 2a45dbc97d7..e750c450507 100644 --- a/base/applications/CMakeLists.txt +++ b/base/applications/CMakeLists.txt @@ -18,7 +18,7 @@ add_subdirectory(logoff) add_subdirectory(magnify) add_subdirectory(mmc) add_subdirectory(mplay32) -# add_subdirectory(msconfig) +add_subdirectory(msconfig) add_subdirectory(mscutils) add_subdirectory(mstsc) add_subdirectory(network) diff --git a/base/applications/cacls/lang/bg-BG.rc b/base/applications/cacls/lang/bg-BG.rc index 6bf72e5aa48..486feb734da 100644 --- a/base/applications/cacls/lang/bg-BG.rc +++ b/base/applications/cacls/lang/bg-BG.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/ca-ES.rc b/base/applications/cacls/lang/ca-ES.rc index 39158abc0e3..db385d0ab1d 100644 --- a/base/applications/cacls/lang/ca-ES.rc +++ b/base/applications/cacls/lang/ca-ES.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton June, 2011 */ - LANGUAGE LANG_CATALAN, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/cs-CZ.rc b/base/applications/cacls/lang/cs-CZ.rc index 974524ab6c2..7f9fb2975f4 100644 --- a/base/applications/cacls/lang/cs-CZ.rc +++ b/base/applications/cacls/lang/cs-CZ.rc @@ -2,7 +2,6 @@ * FILE: base/applications/cacls/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) * UPDATED: 2008-02-29 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT diff --git a/base/applications/cacls/lang/da-DA.rc b/base/applications/cacls/lang/da-DA.rc index 4e53f85c574..bf9ad4e5a4b 100644 --- a/base/applications/cacls/lang/da-DA.rc +++ b/base/applications/cacls/lang/da-DA.rc @@ -1,6 +1,5 @@ /* - * Danish language file by Daniel Reimer 2006-06-15 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) + * Danish language file by Daniel Reimer 2006-06-15 */ LANGUAGE LANG_DANISH, SUBLANG_DEFAULT diff --git a/base/applications/cacls/lang/de-DE.rc b/base/applications/cacls/lang/de-DE.rc index 66a60e58eb5..c3feb90bff2 100644 --- a/base/applications/cacls/lang/de-DE.rc +++ b/base/applications/cacls/lang/de-DE.rc @@ -1,6 +1,5 @@ /* - * German language file by Daniel Reimer 2006-06-15 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) + * German language file by Daniel Reimer 2006-06-15 */ LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL diff --git a/base/applications/cacls/lang/el-GR.rc b/base/applications/cacls/lang/el-GR.rc index 11122ef032f..22f8701f47c 100644 --- a/base/applications/cacls/lang/el-GR.rc +++ b/base/applications/cacls/lang/el-GR.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_GREEK, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/es-ES.rc b/base/applications/cacls/lang/es-ES.rc index f48fa9e410e..1cc8fd08b2d 100644 --- a/base/applications/cacls/lang/es-ES.rc +++ b/base/applications/cacls/lang/es-ES.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/fr-FR.rc b/base/applications/cacls/lang/fr-FR.rc index 0668af211f4..b3de320022d 100644 --- a/base/applications/cacls/lang/fr-FR.rc +++ b/base/applications/cacls/lang/fr-FR.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/it-IT.rc b/base/applications/cacls/lang/it-IT.rc index 0f8c4590098..b9993fd286b 100644 --- a/base/applications/cacls/lang/it-IT.rc +++ b/base/applications/cacls/lang/it-IT.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/ja-JP.rc b/base/applications/cacls/lang/ja-JP.rc index 4fc03e13e35..a52cbff4872 100644 --- a/base/applications/cacls/lang/ja-JP.rc +++ b/base/applications/cacls/lang/ja-JP.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/ko-KR.rc b/base/applications/cacls/lang/ko-KR.rc index abb1aff4134..2f8211a456c 100644 --- a/base/applications/cacls/lang/ko-KR.rc +++ b/base/applications/cacls/lang/ko-KR.rc @@ -1,6 +1,5 @@ /* * Korean translation by manatails007 (www.manatails007.org) - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT diff --git a/base/applications/cacls/lang/no-NO.rc b/base/applications/cacls/lang/no-NO.rc index b8a96aad0ee..55d1a64e452 100644 --- a/base/applications/cacls/lang/no-NO.rc +++ b/base/applications/cacls/lang/no-NO.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE diff --git a/base/applications/cacls/lang/sk-SK.rc b/base/applications/cacls/lang/sk-SK.rc index a8d38467d23..79e038ea71e 100644 --- a/base/applications/cacls/lang/sk-SK.rc +++ b/base/applications/cacls/lang/sk-SK.rc @@ -1,6 +1,5 @@ /* * Slovak language file by Mário Kačmár aka Kario (kario@szm.sk) 16-01-2008 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT diff --git a/base/applications/cacls/lang/zh-CN.rc b/base/applications/cacls/lang/zh-CN.rc index b9629af5601..b33b6fdc897 100644 --- a/base/applications/cacls/lang/zh-CN.rc +++ b/base/applications/cacls/lang/zh-CN.rc @@ -2,7 +2,6 @@ * cacls (Simplified Chinese resources) * (简体中文资源) * Copyright 2007 zhangbing - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/base/applications/cacls/lang/zh-TW.rc b/base/applications/cacls/lang/zh-TW.rc index 552cd296f18..965448695aa 100644 --- a/base/applications/cacls/lang/zh-TW.rc +++ b/base/applications/cacls/lang/zh-TW.rc @@ -2,7 +2,6 @@ * cacls (TRADITIONAL Chinese resources) * (繁體中文資源) * Copyright 2007 jauming - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/base/applications/calc/calc.h b/base/applications/calc/calc.h index 1e645e75e84..3b36230b62a 100644 --- a/base/applications/calc/calc.h +++ b/base/applications/calc/calc.h @@ -1,4 +1,3 @@ -#pragma once #include #include diff --git a/base/applications/calc/fun_mpfr.c b/base/applications/calc/fun_mpfr.c index e52193b6209..8d1534048a2 100644 --- a/base/applications/calc/fun_mpfr.c +++ b/base/applications/calc/fun_mpfr.c @@ -1,5 +1,4 @@ #include "calc.h" -#include void apply_int_mask(calc_number_t *r) { diff --git a/base/applications/calc/function.c b/base/applications/calc/function.c index 2da681ff26b..82bd6f46617 100644 --- a/base/applications/calc/function.c +++ b/base/applications/calc/function.c @@ -1,5 +1,4 @@ #include "calc.h" -#include void apply_int_mask(calc_number_t *r) { diff --git a/base/applications/calc/lang/bg-BG.rc b/base/applications/calc/lang/bg-BG.rc index d2fc871f294..71cb186ada3 100644 --- a/base/applications/calc/lang/bg-BG.rc +++ b/base/applications/calc/lang/bg-BG.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - //Недовършен LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT diff --git a/base/applications/calc/lang/cs-CZ.rc b/base/applications/calc/lang/cs-CZ.rc index 4835532424e..95f2cb04458 100644 --- a/base/applications/calc/lang/cs-CZ.rc +++ b/base/applications/calc/lang/cs-CZ.rc @@ -1,7 +1,6 @@ /* FILE: base/applications/calc/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) * UPDATED: 2010-05-30 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT diff --git a/base/applications/calc/lang/de-DE.rc b/base/applications/calc/lang/de-DE.rc index 182c2456af6..a3561fc421d 100644 --- a/base/applications/calc/lang/de-DE.rc +++ b/base/applications/calc/lang/de-DE.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL // Dialog diff --git a/base/applications/calc/lang/el-GR.rc b/base/applications/calc/lang/el-GR.rc index cc291402c80..f11de0ba3a3 100644 --- a/base/applications/calc/lang/el-GR.rc +++ b/base/applications/calc/lang/el-GR.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_GREEK, SUBLANG_DEFAULT // Dialog diff --git a/base/applications/calc/lang/es-ES.rc b/base/applications/calc/lang/es-ES.rc index 203630a0b4c..4d4f8d609b9 100644 --- a/base/applications/calc/lang/es-ES.rc +++ b/base/applications/calc/lang/es-ES.rc @@ -1,7 +1,6 @@ /* * Spanish Language resource file * Traducido por: Javier Remacha 2008 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL diff --git a/base/applications/calc/lang/fr-FR.rc b/base/applications/calc/lang/fr-FR.rc index f455536eddb..43dd5086cb9 100644 --- a/base/applications/calc/lang/fr-FR.rc +++ b/base/applications/calc/lang/fr-FR.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL // Dialog diff --git a/base/applications/calc/lang/it-IT.rc b/base/applications/calc/lang/it-IT.rc index a4c6deee99d..607e95871e8 100644 --- a/base/applications/calc/lang/it-IT.rc +++ b/base/applications/calc/lang/it-IT.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL // Dialog diff --git a/base/applications/calc/lang/ja-JP.rc b/base/applications/calc/lang/ja-JP.rc index b97fc0b74e6..0f94e4d0cfb 100644 --- a/base/applications/calc/lang/ja-JP.rc +++ b/base/applications/calc/lang/ja-JP.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT // Dialog diff --git a/base/applications/calc/lang/ko-KR.rc b/base/applications/calc/lang/ko-KR.rc index 26eec1a8b74..8069dc2e05c 100644 --- a/base/applications/calc/lang/ko-KR.rc +++ b/base/applications/calc/lang/ko-KR.rc @@ -1,6 +1,5 @@ /* - * Korean translation by manatails007 (www.manatails007.org) Seungju Kim - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) + * Korean translation by manatails007 (www.manatails007.org) Seungju Kim */ LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT diff --git a/base/applications/calc/lang/no-NO.rc b/base/applications/calc/lang/no-NO.rc index 65fae54a70d..1b85033c33e 100644 --- a/base/applications/calc/lang/no-NO.rc +++ b/base/applications/calc/lang/no-NO.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL // Dialog diff --git a/base/applications/calc/lang/sk-SK.rc b/base/applications/calc/lang/sk-SK.rc index 263f5d4f47c..644cb1875fa 100644 --- a/base/applications/calc/lang/sk-SK.rc +++ b/base/applications/calc/lang/sk-SK.rc @@ -1,7 +1,6 @@ /* TRANSLATOR : Mário Kačmár /Mario Kacmar/ aka Kario (kario@szm.sk) * DATE OF TR.: 30-01-2008 * LAST CHANGE: 17-09-2010 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) * --------------------------------------- * TODO: * pridanie navigačných značiek "&" ? diff --git a/base/applications/calc/lang/sv-SE.rc b/base/applications/calc/lang/sv-SE.rc index fbf1ab2a212..4b63dc8f2cc 100644 --- a/base/applications/calc/lang/sv-SE.rc +++ b/base/applications/calc/lang/sv-SE.rc @@ -3,7 +3,6 @@ * FILE: base\applications\calc\lang\sv-SE.rc * PURPOSE: Swedish resource file * Translation: Jaix Bly - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL diff --git a/base/applications/calc/lang/th-TH.rc b/base/applications/calc/lang/th-TH.rc index 61c3768db5b..a0f5593e152 100644 --- a/base/applications/calc/lang/th-TH.rc +++ b/base/applications/calc/lang/th-TH.rc @@ -1,7 +1,6 @@ /* * ReactOS Calc (Thai resource file) * Last modified: 2009-02-02 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_THAI, SUBLANG_DEFAULT diff --git a/base/applications/charmap/lang/bg-BG.rc b/base/applications/charmap/lang/bg-BG.rc index b1fda22afc2..6f6fa36607a 100644 --- a/base/applications/charmap/lang/bg-BG.rc +++ b/base/applications/charmap/lang/bg-BG.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT IDD_CHARMAP DIALOGEX 6, 6, 292, 224 diff --git a/base/applications/charmap/lang/cs-CZ.rc b/base/applications/charmap/lang/cs-CZ.rc index a2dc5eb8e8c..326a7a55dfb 100644 --- a/base/applications/charmap/lang/cs-CZ.rc +++ b/base/applications/charmap/lang/cs-CZ.rc @@ -1,7 +1,6 @@ /* FILE: applications/charmap/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) * UPDATED: 2011-03-31 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT diff --git a/base/applications/charmap/lang/de-DE.rc b/base/applications/charmap/lang/de-DE.rc index d1b083bf1f7..e85e0326eda 100644 --- a/base/applications/charmap/lang/de-DE.rc +++ b/base/applications/charmap/lang/de-DE.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL IDD_CHARMAP DIALOGEX 6, 6, 292, 224 diff --git a/base/applications/charmap/lang/el-GR.rc b/base/applications/charmap/lang/el-GR.rc index bc944db50a1..edcc283fcf3 100644 --- a/base/applications/charmap/lang/el-GR.rc +++ b/base/applications/charmap/lang/el-GR.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_GREEK, SUBLANG_DEFAULT IDD_CHARMAP DIALOGEX 6, 6, 292, 224 diff --git a/base/applications/charmap/lang/es-ES.rc b/base/applications/charmap/lang/es-ES.rc index b45467223e9..a15d8b3fe70 100644 --- a/base/applications/charmap/lang/es-ES.rc +++ b/base/applications/charmap/lang/es-ES.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL IDD_CHARMAP DIALOGEX 6, 6, 292, 224 diff --git a/base/applications/charmap/lang/ja-JP.rc b/base/applications/charmap/lang/ja-JP.rc index de781319872..c32cf8ae32c 100644 --- a/base/applications/charmap/lang/ja-JP.rc +++ b/base/applications/charmap/lang/ja-JP.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT IDD_CHARMAP DIALOGEX 6, 6, 292, 224 diff --git a/base/applications/charmap/lang/ko-KR.rc b/base/applications/charmap/lang/ko-KR.rc index 3dbfb184c49..1be87c3af9e 100644 --- a/base/applications/charmap/lang/ko-KR.rc +++ b/base/applications/charmap/lang/ko-KR.rc @@ -1,6 +1,5 @@ /* * Korean translation by manatails007(www.manatails007.org) - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT diff --git a/base/applications/charmap/lang/lt-LT.rc b/base/applications/charmap/lang/lt-LT.rc index 37c9e3b2d03..9d5767c04a0 100644 --- a/base/applications/charmap/lang/lt-LT.rc +++ b/base/applications/charmap/lang/lt-LT.rc @@ -5,7 +5,6 @@ * PURPOSE: Lithuanian Language File * TRANSLATOR: Vytis "CMan" Girdþijauskas (cman@cman.us) * DATE: 2007-09-23 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_LITHUANIAN, SUBLANG_DEFAULT diff --git a/base/applications/charmap/lang/pt-BR.rc b/base/applications/charmap/lang/pt-BR.rc index bdc2f1dc29a..5abe94c9311 100644 --- a/base/applications/charmap/lang/pt-BR.rc +++ b/base/applications/charmap/lang/pt-BR.rc @@ -1,5 +1,3 @@ -/* UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ - LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL IDD_CHARMAP DIALOGEX 6, 6, 292, 224 diff --git a/base/applications/charmap/lang/sk-SK.rc b/base/applications/charmap/lang/sk-SK.rc index 9e4b31f804d..3f1477013c9 100644 --- a/base/applications/charmap/lang/sk-SK.rc +++ b/base/applications/charmap/lang/sk-SK.rc @@ -5,7 +5,6 @@ * TRANSLATOR: Kario (kario@szm.sk) /Mário Kačmár/ * DATE OF TR.: 24-07-2007 * LAST CHANGE: 29-08-2008 - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT diff --git a/base/applications/charmap/lang/sv-SE.rc b/base/applications/charmap/lang/sv-SE.rc index 5ac57e01c78..475f38f818f 100644 --- a/base/applications/charmap/lang/sv-SE.rc +++ b/base/applications/charmap/lang/sv-SE.rc @@ -3,7 +3,6 @@ * FILE: base\applications\charmap\lang\sv-SE.rc * PURPOSE: Swedish resource file * TRANSLATOR: Jaix Bly - * UTF-8 Conversion: Elton Chung aka MfldElton (June, 2011) */ LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL diff --git a/base/applications/cmdutils/doskey/doskey.rc b/base/applications/cmdutils/doskey/doskey.rc index bc50e30b439..100ecc561a5 100644 --- a/base/applications/cmdutils/doskey/doskey.rc +++ b/base/applications/cmdutils/doskey/doskey.rc @@ -15,3 +15,4 @@ #pragma code_page(65001) #include "lang/pl-PL.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/cmdutils/doskey/lang/zh-CN.rc b/base/applications/cmdutils/doskey/lang/zh-CN.rc new file mode 100644 index 00000000000..6f3fffadd93 --- /dev/null +++ b/base/applications/cmdutils/doskey/lang/zh-CN.rc @@ -0,0 +1,31 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + +IDS_HELP, "管理命令行编辑设置、历史记录和宏。\n\ +\n\ +DOSKEY [/INSERT | /OVERSTRIKE] [/EXENAME=exe] [/HISTORY] [/LISTSIZE=大小]\n\ + [/REINSTALL] [/MACROS[:exe | :ALL]] [/MACROFILE=文件] [宏名=[文本]]\n\ +\n\ + /INSERT 开启插入模式。\n\ + /OVERSTRIKE \n\ + /EXENAME=exename 设置要查看或改变历史记录和宏的程序名。\n\ + 默认为 cmd.exe。\n\ + /HISTORY 显示命令历史。\n\ + /LISTSIZE=size 设置每个历史记录缓存记录的命令数。\n\ + /REINSTALL 清空命令历史记录。\n\ + /MACROS 显示定义的宏。\n\ + /MACROS:exename 显示为指定程序定义的宏。\n\ + /MACROS:ALL 显示为所有程序定义的宏。\n\ + /MACROFILE=file 从文件载入宏定义。\n\ + 宏名 指定要创建的宏名。\n\ + 文本 指定要替换该宏的文本。\n" + +IDS_INVALID_MACRO_DEF, "无效的宏定义:%s\n" + +END diff --git a/base/applications/cmdutils/find/lang/zh-CN.rc b/base/applications/cmdutils/find/lang/zh-CN.rc new file mode 100644 index 00000000000..dc545fd85c7 --- /dev/null +++ b/base/applications/cmdutils/find/lang/zh-CN.rc @@ -0,0 +1,21 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + +IDS_USAGE, "FIND: 输出某文件中包含指定字符串的所有行。\n\n\ + FIND [ /C ] [ /I ] [ /N ] [ /V ] ""字符串"" [ 文件... ]\n\ + /C 计算包含该字符串的行数\n\ + /I 忽略大小写\n\ + /N 从 1 开始为显示的行编号\n\ + /V 输出不包含该指定字符串的行" + +IDS_NO_SUCH_FILE, "FIND: %s: 没有这个文件\n" + +IDS_CANNOT_OPEN, "FIND: %s: 无法打开文件\n" + +END diff --git a/base/applications/cmdutils/find/rsrc.rc b/base/applications/cmdutils/find/rsrc.rc index 93f89c16048..f0638ab8b6f 100644 --- a/base/applications/cmdutils/find/rsrc.rc +++ b/base/applications/cmdutils/find/rsrc.rc @@ -21,3 +21,4 @@ #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/cmdutils/more/lang/zh-CN.rc b/base/applications/cmdutils/more/lang/zh-CN.rc new file mode 100644 index 00000000000..c9aab8d256b --- /dev/null +++ b/base/applications/cmdutils/more/lang/zh-CN.rc @@ -0,0 +1,19 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + IDS_USAGE, "在屏幕上一页一页地显示内容。\n\n\ + MORE < [驱动器:][路径]文件名\n\ + 命令 | MORE \n\ + MORE [驱动器:][路径]文件名\n\n\ + [驱动器:][路径]文件名 一个将要被如此显示内容的文件。\n\ + 命令\t\t 一个输出将要被如此显示的命令。\n\n\ + 在 ""-- 继续 --"" 的提示出现时你可以按任意键来显示下一页。\n" + + IDS_CONTINUE, " -- 继续 (100%) -- " + IDS_FILE_ACCESS, "无法访问文件 %s。" +END diff --git a/base/applications/cmdutils/more/rsrc.rc b/base/applications/cmdutils/more/rsrc.rc index 26ee145fee0..d01b4c61bbc 100644 --- a/base/applications/cmdutils/more/rsrc.rc +++ b/base/applications/cmdutils/more/rsrc.rc @@ -17,3 +17,4 @@ #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/dxdiag/display.c b/base/applications/dxdiag/display.c index a67db53fee2..5cef4efb698 100644 --- a/base/applications/dxdiag/display.c +++ b/base/applications/dxdiag/display.c @@ -9,8 +9,6 @@ #include "precomp.h" #include -#include -#include BOOL GetFileModifyTime(LPCWSTR pFullPath, WCHAR * szTime, int szTimeSize) diff --git a/base/applications/dxdiag/precomp.h b/base/applications/dxdiag/precomp.h index 05200f7b2d5..cbb999b1c18 100644 --- a/base/applications/dxdiag/precomp.h +++ b/base/applications/dxdiag/precomp.h @@ -12,7 +12,8 @@ #include #include #include - +#include +#include #include #include #include diff --git a/base/applications/dxdiag/sound.c b/base/applications/dxdiag/sound.c index 4a84c9c6342..59a9293f6c5 100644 --- a/base/applications/dxdiag/sound.c +++ b/base/applications/dxdiag/sound.c @@ -8,7 +8,6 @@ */ #include "precomp.h" -#include #include #if 0 diff --git a/base/applications/findstr/lang/zh-CN.rc b/base/applications/findstr/lang/zh-CN.rc new file mode 100644 index 00000000000..35fa9b34cf1 --- /dev/null +++ b/base/applications/findstr/lang/zh-CN.rc @@ -0,0 +1,17 @@ +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + +IDS_USAGE, "FINDSTR: 输出某文件中包含指定字符串的所有行。\n\n\ + FINDSTR [ /C ] [ /I ] [ /N ] [ /V ] ""字符串"" [ 文件... ]\n\ + /C 计算包含该字符串的行数\n\ + /I 忽略大小写\n\ + /N 从 1 开始为显示的行编号\n\ + /V 输出不包含该指定字符串的行" + +IDS_NO_SUCH_FILE, "FINDSTR: %s: 没有这个文件\n" + +IDS_CANNOT_OPEN, "FINDSTR: %s: 无法打开文件\n" + +END diff --git a/base/applications/findstr/rsrc.rc b/base/applications/findstr/rsrc.rc index de7ca5a5faa..1c6773c36a0 100644 --- a/base/applications/findstr/rsrc.rc +++ b/base/applications/findstr/rsrc.rc @@ -22,3 +22,4 @@ #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/games/solitaire/CMakeLists.txt b/base/applications/games/solitaire/CMakeLists.txt index 2a4c737f685..b638a0a670e 100644 --- a/base/applications/games/solitaire/CMakeLists.txt +++ b/base/applications/games/solitaire/CMakeLists.txt @@ -12,9 +12,7 @@ add_executable(sol rsrc.rc) target_link_libraries(sol cardlib) - +add_pch(sol solitaire.h) set_module_type(sol win32gui) - add_importlibs(sol advapi32 comctl32 user32 gdi32 msvcrt kernel32) - add_cd_file(TARGET sol DESTINATION reactos/system32 FOR all) diff --git a/base/applications/games/solitaire/lang/sv-SE.rc b/base/applications/games/solitaire/lang/sv-SE.rc new file mode 100644 index 00000000000..d045ff37974 --- /dev/null +++ b/base/applications/games/solitaire/lang/sv-SE.rc @@ -0,0 +1,92 @@ +/* + * PROJECT: Solitaire + * LICENSE: Freeware, permission to use under Public Domain + * FILE: base/applications/games/solitaire/lang/en-US.rc + * PURPOSE: English Language File for Solitaire + * PROGRAMMERS: Daniel "EmuandCo" Reimer (reimer.daniel@freenet.de) + */ +LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL + + +/* Dialogs */ + +IDD_OPTIONS DIALOGEX DISCARDABLE 0, 0, 186, 118 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "Options" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Kort", -1, 7, 7, 65, 40 + AUTORADIOBUTTON "Dra &En", IDC_OPT_DRAWONE, 14, 19, 52, 10, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "Dra &Tre", IDC_OPT_DRAWTHREE, 14, 32, 52, 10 + + AUTOCHECKBOX "&Visa Tid", IDC_OPT_SHOWTIME, 7 ,51 ,65 ,10, WS_TABSTOP | WS_DISABLED + AUTOCHECKBOX "&Statusfält", IDC_OPT_STATUSBAR, 7, 66, 64, 10, WS_TABSTOP + + DEFPUSHBUTTON "OK", IDOK, 35, 97, 50, 14 + PUSHBUTTON "Avbryt", IDCANCEL, 101, 97, 50, 14 +END + + +IDD_CARDBACK DIALOGEX 6, 6, 186, 104 +CAPTION "Välj Kort Baksida" +FONT 8, "MS Shell Dlg" +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +BEGIN + CONTROL "", IDC_CARDBACK1, "Static", SS_NOTIFY, 4, 7, 26, 32 + CONTROL "", IDC_CARDBACK2, "Static", SS_NOTIFY, 34, 7, 26, 32 + CONTROL "", IDC_CARDBACK3, "Static", SS_NOTIFY, 64, 7, 26, 32 + CONTROL "", IDC_CARDBACK4, "Static", SS_NOTIFY, 94, 7, 26, 32 + CONTROL "", IDC_CARDBACK5, "Static", SS_NOTIFY, 124, 7, 26, 32 + CONTROL "", IDC_CARDBACK6, "Static", SS_NOTIFY, 154, 7, 26, 32 + CONTROL "", IDC_CARDBACK7, "Static", SS_NOTIFY, 4, 46, 26, 32 + CONTROL "", IDC_CARDBACK8, "Static", SS_NOTIFY, 34, 46, 26, 32 + CONTROL "", IDC_CARDBACK9, "Static", SS_NOTIFY, 64, 46, 26, 32 + CONTROL "", IDC_CARDBACK10, "Static", SS_NOTIFY, 94, 46, 26, 32 + CONTROL "", IDC_CARDBACK11, "Static", SS_NOTIFY, 124, 46, 26, 32 + CONTROL "", IDC_CARDBACK12, "Static", SS_NOTIFY, 154, 46, 26, 32 + DEFPUSHBUTTON "OK", IDOK, 66, 84, 54, 13 + PUSHBUTTON "Avbryt", IDCANCEL, 126, 84, 54, 13 +END + + +/* Strings */ + +STRINGTABLE +BEGIN + IDS_SOL_NAME "Solitaire" + IDS_SOL_ABOUT "Solitaire av J Brown\nÖversätt av Ronny K Svensson\n\nCardLib version 1.0." + IDS_SOL_QUIT "Avsluta nuvarande spel?" + IDS_SOL_WIN "Grattis, du vann!" + IDS_SOL_DEAL "Ge igen?" +END + + +/* Menus */ + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "&Spel" + BEGIN + MENUITEM "&Ge\tF2", IDM_GAME_NEW + MENUITEM SEPARATOR + MENUITEM "&Kortlek...", IDM_GAME_DECK + MENUITEM "&Alternativ...", IDM_GAME_OPTIONS + MENUITEM SEPARATOR + MENUITEM "&Avsluta", IDM_GAME_EXIT + END + POPUP "&Hjälp" + BEGIN + MENUITEM "&Innehåll\tF1", IDM_HELP_CONTENTS + MENUITEM "&Om", IDM_HELP_ABOUT + END +END + + + +/* Accelerator */ + +IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE +BEGIN + VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT + VK_F2, IDM_GAME_NEW, VIRTKEY, NOINVERT +END diff --git a/base/applications/games/solitaire/rsrc.rc b/base/applications/games/solitaire/rsrc.rc index 0614ccd5d8c..e1c90611223 100644 --- a/base/applications/games/solitaire/rsrc.rc +++ b/base/applications/games/solitaire/rsrc.rc @@ -23,6 +23,7 @@ IDI_SOLITAIRE ICON DISCARDABLE "solitaire.ico" #include "lang/nl-NL.rc" #include "lang/no-NO.rc" #include "lang/sk-SK.rc" +#include "lang/sv-SE.rc" #include "lang/th-TH.rc" #include "lang/zh-CN.rc" diff --git a/base/applications/games/solitaire/solcreate.cpp b/base/applications/games/solitaire/solcreate.cpp index 0b29d246cca..7166ef7e195 100644 --- a/base/applications/games/solitaire/solcreate.cpp +++ b/base/applications/games/solitaire/solcreate.cpp @@ -1,8 +1,3 @@ -#include -#include -#include -#include "resource.h" -#include "cardlib.h" #include "solitaire.h" diff --git a/base/applications/games/solitaire/solgame.cpp b/base/applications/games/solitaire/solgame.cpp index 2709f1ed2a4..f809071961a 100644 --- a/base/applications/games/solitaire/solgame.cpp +++ b/base/applications/games/solitaire/solgame.cpp @@ -1,9 +1,4 @@ -#include -#include -#include -#include -#include "resource.h" -#include "cardlib.h" + #include "solitaire.h" #if 1 diff --git a/base/applications/games/solitaire/solitaire.cpp b/base/applications/games/solitaire/solitaire.cpp index 4046b92ff2a..bf45a53e9bd 100644 --- a/base/applications/games/solitaire/solitaire.cpp +++ b/base/applications/games/solitaire/solitaire.cpp @@ -1,10 +1,3 @@ -#include -#include -#include -#include - -#include "resource.h" -#include "cardlib.h" #include "solitaire.h" diff --git a/base/applications/games/solitaire/solitaire.h b/base/applications/games/solitaire/solitaire.h index ae52831b073..ddd00ad5bf3 100644 --- a/base/applications/games/solitaire/solitaire.h +++ b/base/applications/games/solitaire/solitaire.h @@ -1,4 +1,11 @@ -#pragma once + +#include +#include +#include +#include +#include +#include "resource.h" +#include "cardlib.h" extern CardWindow SolWnd; extern TCHAR szAppName[]; diff --git a/base/applications/games/spider/CMakeLists.txt b/base/applications/games/spider/CMakeLists.txt index cf44a846995..9e2f84c5c47 100644 --- a/base/applications/games/spider/CMakeLists.txt +++ b/base/applications/games/spider/CMakeLists.txt @@ -12,9 +12,7 @@ add_executable(spider rsrc.rc) target_link_libraries(spider cardlib) - +add_pch(spider spider.h) set_module_type(spider win32gui) - add_importlibs(spider advapi32 comctl32 user32 gdi32 msvcrt kernel32) - add_cd_file(TARGET spider DESTINATION reactos/system32 FOR all) diff --git a/base/applications/games/spider/lang/sv-SE.rc b/base/applications/games/spider/lang/sv-SE.rc new file mode 100644 index 00000000000..c6af7ec7b0b --- /dev/null +++ b/base/applications/games/spider/lang/sv-SE.rc @@ -0,0 +1,89 @@ +/* + * PROJECT: Spider Solitaire + * LICENSE: See COPYING in top level directory + * FILE: base/applications/games/spider/lang/en-US.rc + * PURPOSE: English Language File for Spider Solitaire + * TRANSLATOR: Gregor Schneider + */ + +#include "resource.h" + +LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL + + +/* Dialogs */ + +IDD_CARDBACK DIALOGEX 6, 6, 186, 104 +CAPTION "Välj Kort Baksidan" +FONT 8, "MS Shell Dlg" +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +BEGIN + CONTROL "", IDC_CARDBACK1, "Static", SS_NOTIFY, 4, 7, 26, 32 + CONTROL "", IDC_CARDBACK2, "Static", SS_NOTIFY, 34, 7, 26, 32 + CONTROL "", IDC_CARDBACK3, "Static", SS_NOTIFY, 64, 7, 26, 32 + CONTROL "", IDC_CARDBACK4, "Static", SS_NOTIFY, 94, 7, 26, 32 + CONTROL "", IDC_CARDBACK5, "Static", SS_NOTIFY, 124, 7, 26, 32 + CONTROL "", IDC_CARDBACK6, "Static", SS_NOTIFY, 154, 7, 26, 32 + CONTROL "", IDC_CARDBACK7, "Static", SS_NOTIFY, 4, 46, 26, 32 + CONTROL "", IDC_CARDBACK8, "Static", SS_NOTIFY, 34, 46, 26, 32 + CONTROL "", IDC_CARDBACK9, "Static", SS_NOTIFY, 64, 46, 26, 32 + CONTROL "", IDC_CARDBACK10, "Static", SS_NOTIFY, 94, 46, 26, 32 + CONTROL "", IDC_CARDBACK11, "Static", SS_NOTIFY, 124, 46, 26, 32 + CONTROL "", IDC_CARDBACK12, "Static", SS_NOTIFY, 154, 46, 26, 32 + DEFPUSHBUTTON "OK", IDOK, 66, 84, 54, 13 + PUSHBUTTON "Avbryt", IDCANCEL, 126, 84, 54, 13 +END + +IDD_DIFFICULTY DIALOGEX DISCARDABLE 100, 100, 106, 80 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "Svårighet" +FONT 8, "MS Shell Dlg" +BEGIN + AUTORADIOBUTTON "Lätt: &En Färg", IDC_DIF_ONECOLOR, 8, 10, 80, 10, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "Medel: &Två Färger", IDC_DIF_TWOCOLORS, 8, 23, 80, 10 + AUTORADIOBUTTON "Svårt: &Fyra Färger", IDC_DIF_FOURCOLORS, 8, 36, 80, 10 + + DEFPUSHBUTTON "OK", IDOK, 8, 58, 40, 14 + PUSHBUTTON "Avbryt", IDCANCEL, 58, 58, 40, 14 +END + +/* Strings */ + +STRINGTABLE +BEGIN + IDS_SPI_NAME "Spider" + IDS_SPI_ABOUT "Spider Solitaire av Gregor Schneider\nÖversätt av Ronny K Svensson\n\nCardLib version 1.0" + IDS_SPI_QUIT "Avsluta ditt nuvarande spel?" + IDS_SPI_WIN "Grattis, du vann!" + IDS_SPI_DEAL "Ge igen?" +END + + +/* Menus */ + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "&Spel" + BEGIN + MENUITEM "&Nytt spel\tF2", IDM_GAME_NEW + MENUITEM SEPARATOR + MENUITEM "&Kortlek...", IDM_GAME_DECK + MENUITEM SEPARATOR + MENUITEM "&Avsluta", IDM_GAME_EXIT + END + POPUP "&Hjälp" + BEGIN + MENUITEM "&Innehåll\tF1", IDM_HELP_CONTENTS + MENUITEM "&Om", IDM_HELP_ABOUT + END +END + + + +/* Accelerator */ + +IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE +BEGIN + VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT + VK_F2, IDM_GAME_NEW, VIRTKEY, NOINVERT +END diff --git a/base/applications/games/spider/lang/zh-CN.rc b/base/applications/games/spider/lang/zh-CN.rc new file mode 100644 index 00000000000..56e4aa1cf1c --- /dev/null +++ b/base/applications/games/spider/lang/zh-CN.rc @@ -0,0 +1,89 @@ +/* + * PROJECT: Spider Solitaire + * LICENSE: See COPYING in top level directory + * FILE: base/applications/games/spider/lang/zh-CN.rc + * PURPOSE: Chinese Language File for Spider Solitaire + * TRANSLATOR: Song Fuchang (0xfc) + */ + +#include "resource.h" + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + + +/* Dialogs */ + +IDD_CARDBACK DIALOGEX 6, 6, 186, 104 +CAPTION "选择牌背图案" +FONT 8, "MS Shell Dlg" +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +BEGIN + CONTROL "", IDC_CARDBACK1, "Static", SS_NOTIFY, 4, 7, 26, 32 + CONTROL "", IDC_CARDBACK2, "Static", SS_NOTIFY, 34, 7, 26, 32 + CONTROL "", IDC_CARDBACK3, "Static", SS_NOTIFY, 64, 7, 26, 32 + CONTROL "", IDC_CARDBACK4, "Static", SS_NOTIFY, 94, 7, 26, 32 + CONTROL "", IDC_CARDBACK5, "Static", SS_NOTIFY, 124, 7, 26, 32 + CONTROL "", IDC_CARDBACK6, "Static", SS_NOTIFY, 154, 7, 26, 32 + CONTROL "", IDC_CARDBACK7, "Static", SS_NOTIFY, 4, 46, 26, 32 + CONTROL "", IDC_CARDBACK8, "Static", SS_NOTIFY, 34, 46, 26, 32 + CONTROL "", IDC_CARDBACK9, "Static", SS_NOTIFY, 64, 46, 26, 32 + CONTROL "", IDC_CARDBACK10, "Static", SS_NOTIFY, 94, 46, 26, 32 + CONTROL "", IDC_CARDBACK11, "Static", SS_NOTIFY, 124, 46, 26, 32 + CONTROL "", IDC_CARDBACK12, "Static", SS_NOTIFY, 154, 46, 26, 32 + DEFPUSHBUTTON "确定", IDOK, 66, 84, 54, 13 + PUSHBUTTON "取消", IDCANCEL, 126, 84, 54, 13 +END + +IDD_DIFFICULTY DIALOGEX DISCARDABLE 100, 100, 106, 80 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "难度" +FONT 8, "MS Shell Dlg" +BEGIN + AUTORADIOBUTTON "简单:一种颜色(&O)", IDC_DIF_ONECOLOR, 8, 10, 80, 10, WS_GROUP | WS_TABSTOP + AUTORADIOBUTTON "中等:两种颜色(&T)", IDC_DIF_TWOCOLORS, 8, 23, 80, 10 + AUTORADIOBUTTON "困难:四种颜色(&F)", IDC_DIF_FOURCOLORS, 8, 36, 80, 10 + + DEFPUSHBUTTON "确定", IDOK, 8, 58, 40, 14 + PUSHBUTTON "取消", IDCANCEL, 58, 58, 40, 14 +END + +/* Strings */ + +STRINGTABLE +BEGIN + IDS_SPI_NAME "蜘蛛纸牌" + IDS_SPI_ABOUT "蜘蛛纸牌 作者:Gregor Schneider\n\n使用 CardLib 版本 1.0" + IDS_SPI_QUIT "退出当前游戏吗?" + IDS_SPI_WIN "祝贺您赢了!" + IDS_SPI_DEAL "再来一次吗?" +END + + +/* Menus */ + +IDR_MENU1 MENU DISCARDABLE +BEGIN + POPUP "游戏(&G)" + BEGIN + MENUITEM "新游戏(&N)\tF2", IDM_GAME_NEW + MENUITEM SEPARATOR + MENUITEM "纸牌... (&D)", IDM_GAME_DECK + MENUITEM SEPARATOR + MENUITEM "退出(&E)", IDM_GAME_EXIT + END + POPUP "帮助(&H)" + BEGIN + MENUITEM "帮助正文(&C)\tF1", IDM_HELP_CONTENTS + MENUITEM "关于(&A)", IDM_HELP_ABOUT + END +END + + + +/* Accelerator */ + +IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE +BEGIN + VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT + VK_F2, IDM_GAME_NEW, VIRTKEY, NOINVERT +END diff --git a/base/applications/games/spider/rsrc.rc b/base/applications/games/spider/rsrc.rc index adfb83be8cd..b3c03b68e16 100644 --- a/base/applications/games/spider/rsrc.rc +++ b/base/applications/games/spider/rsrc.rc @@ -15,9 +15,11 @@ IDI_SPIDER ICON DISCARDABLE "spider.ico" #include "lang/ja-JP.rc" #include "lang/nl-NL.rc" #include "lang/sk-SK.rc" +#include "lang/sv-SE.rc" // UTF-8 #pragma code_page(65001) #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/games/spider/spider.cpp b/base/applications/games/spider/spider.cpp index 49676433234..0df7f9982b0 100644 --- a/base/applications/games/spider/spider.cpp +++ b/base/applications/games/spider/spider.cpp @@ -6,13 +6,6 @@ * PROGRAMMER: Gregor Schneider */ -#include -#include -#include -#include - -#include "resource.h" -#include "cardlib.h" #include "spider.h" TCHAR szHelpPath[MAX_PATH]; diff --git a/base/applications/games/spider/spider.h b/base/applications/games/spider/spider.h index 17b919b91aa..f71d6e384dc 100644 --- a/base/applications/games/spider/spider.h +++ b/base/applications/games/spider/spider.h @@ -1,4 +1,12 @@ -#pragma once + +#include +#include +#include +#include +#include +#include "resource.h" +#include "cardlib.h" + #define DIFFICULTY_ONE_COLOR 1 #define DIFFICULTY_TWO_COLORS 2 diff --git a/base/applications/games/spider/spigame.cpp b/base/applications/games/spider/spigame.cpp index 7521bdd5bdb..5e75ebb9a1f 100644 --- a/base/applications/games/spider/spigame.cpp +++ b/base/applications/games/spider/spigame.cpp @@ -6,13 +6,6 @@ * PROGRAMMER: Gregor Schneider */ -#include -#include -#include -#include - -#include "resource.h" -#include "cardlib.h" #include "spider.h" #define NUM_DECK_CARDS 5 diff --git a/base/applications/magnify/CMakeLists.txt b/base/applications/magnify/CMakeLists.txt index e7ab404c53c..5fef7d5444d 100644 --- a/base/applications/magnify/CMakeLists.txt +++ b/base/applications/magnify/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(magnify settings.c magnify.rc) +add_pch(magnify magnifier.h) set_module_type(magnify win32gui) add_importlibs(magnify user32 gdi32 advapi32 shell32 msvcrt kernel32) add_cd_file(TARGET magnify DESTINATION reactos/system32 FOR all) diff --git a/base/applications/magnify/magnifier.c b/base/applications/magnify/magnifier.c index af0358639a9..31435bf63e2 100644 --- a/base/applications/magnify/magnifier.c +++ b/base/applications/magnify/magnifier.c @@ -7,10 +7,7 @@ * */ -#include -#include #include "magnifier.h" -#include "resource.h" const TCHAR szWindowClass[] = TEXT("MAGNIFIER"); diff --git a/base/applications/magnify/magnifier.h b/base/applications/magnify/magnifier.h index 8728c02fb88..1181c9c4882 100644 --- a/base/applications/magnify/magnifier.h +++ b/base/applications/magnify/magnifier.h @@ -20,6 +20,12 @@ ////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include "resource.h" + extern int iZoom; extern BOOL bShowWarning; diff --git a/base/applications/magnify/magnify.rc b/base/applications/magnify/magnify.rc index 9ea3ddcab6a..f9f04ee5753 100644 --- a/base/applications/magnify/magnify.rc +++ b/base/applications/magnify/magnify.rc @@ -1,6 +1,5 @@ -#include -#include -#include "resource.h" + +#include "magnifier.h" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/base/applications/magnify/settings.c b/base/applications/magnify/settings.c index 3d6f9682f0c..b0119b0a40f 100644 --- a/base/applications/magnify/settings.c +++ b/base/applications/magnify/settings.c @@ -1,5 +1,4 @@ -#include -#include + #include "magnifier.h" int iZoom = 3; diff --git a/base/applications/mplay32/lang/zh-CN.rc b/base/applications/mplay32/lang/zh-CN.rc new file mode 100644 index 00000000000..8b56ac44d3f --- /dev/null +++ b/base/applications/mplay32/lang/zh-CN.rc @@ -0,0 +1,34 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDR_MAINMENU MENU +BEGIN + POPUP "文件(&F)" + BEGIN + MENUITEM "打开... (&O)", IDM_OPEN_FILE + MENUITEM "关闭(&C)", IDM_CLOSE_FILE + MENUITEM SEPARATOR + MENUITEM "退出(&E)", IDM_EXIT + END + POPUP "帮助(&H)" + BEGIN + MENUITEM "关于... (&A)", IDM_ABOUT + END +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_ALL_TYPES_FILTER "所有支持的格式 (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0" + IDS_TOOLTIP_PLAY "播放" + IDS_TOOLTIP_STOP "停止" + IDS_TOOLTIP_EJECT "弹出" + IDS_TOOLTIP_BACKWARD "向后跳过" + IDS_TOOLTIP_SEEKBACK "快退" + IDS_TOOLTIP_SEEKFORW "快进" + IDS_TOOLTIP_FORWARD "向前跳过" + IDS_APPTITLE "ReactOS 多媒体播放器" + IDS_PLAY "播放" +END diff --git a/base/applications/mplay32/rsrc.rc b/base/applications/mplay32/rsrc.rc index aa7bf813a84..6b4f0f0d2cd 100644 --- a/base/applications/mplay32/rsrc.rc +++ b/base/applications/mplay32/rsrc.rc @@ -19,3 +19,4 @@ #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/mscutils/devmgmt/lang/zh-CN.rc b/base/applications/mscutils/devmgmt/lang/zh-CN.rc new file mode 100644 index 00000000000..8a1023fbb1d --- /dev/null +++ b/base/applications/mscutils/devmgmt/lang/zh-CN.rc @@ -0,0 +1,86 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDR_MAINMENU MENU +BEGIN + POPUP "文件(&F)" + BEGIN + MENUITEM "退出(&X)", IDC_EXIT + END + POPUP "动作" + BEGIN + MENUITEM "打印", IDC_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "属性", IDC_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "帮助", IDC_PROGHELP, GRAYED + END + POPUP "查看" + BEGIN + MENUITEM "设备,按类型", IDC_DEVBYTYPE, CHECKED + MENUITEM "设备,按连接", IDC_STATIC, GRAYED + MENUITEM "资源,按类型", IDC_STATIC, GRAYED + MENUITEM "资源,按连接", IDC_STATIC, GRAYED + END + POPUP "帮助" + BEGIN + MENUITEM "帮助内容", IDC_PROGHELP + MENUITEM "关于", IDC_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM "属性", IDC_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "帮助", IDC_PROGHELP + END +END + +IDD_ABOUTBOX DIALOGEX 22,16,190,182 +CAPTION "关于设备管理器" +FONT 8,"MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "设备管理器 v0.1\版权所有 (C) 2006\n作者 Ged Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 130, 30 + PUSHBUTTON "关闭", IDOK, 75, 162, 44, 15 + ICON IDI_MAIN_ICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 174, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "这个程序是自由软件;你可以在自由软件基金会(FSF)的 GNU LGPL 协议下重新发布或修改它;也适用于这个协议的版本 2,或(在您看来)任何更新的版本。\r\n\r\n这个程序在希望其有用的愿望中发布,但没有任何保证;也不意味着性能保证或对某特定用途的适用性。请查看 GNU GPL 许可协议以了解更多细节。\r\n\r\n您应该已经收到了一份和这个程序一起的 GNU GPL 协议的副本;如果没有,请写信给自由软件基金会(FSF):51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_PROP "属性" + IDS_TOOLTIP_REFRESH "刷新" + IDS_TOOLTIP_HELP "帮助" + IDS_TOOLTIP_EXIT "退出" +END + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ReactOS 设备管理器" + IDS_HINT_BLANK " " + IDS_HINT_EXIT " 退出这个程序。" + IDS_HINT_REFRESH " 刷新设备列表。" + IDS_HINT_PROP " 为当前选择项打开属性页。" + IDS_HINT_HELP " 显示帮助窗口。" + IDS_HINT_ABOUT " 关于 ReactOS 设备管理器。" + + IDS_HINT_SYS_RESTORE " 将窗口恢复到默认大小。" + IDS_HINT_SYS_MOVE " 移动这个窗口。" + IDS_HINT_SYS_SIZE " 更改这个窗口的大小。" + IDS_HINT_SYS_MINIMIZE " 将这个窗口折叠为一个图标。" + IDS_HINT_SYS_MAXIMIZE " 将这个窗口扩展到整个屏幕。" + IDS_HINT_SYS_CLOSE " 关闭这个窗口。" +END diff --git a/base/applications/mscutils/devmgmt/rsrc.rc b/base/applications/mscutils/devmgmt/rsrc.rc index e8a04bfc17b..f512433568f 100644 --- a/base/applications/mscutils/devmgmt/rsrc.rc +++ b/base/applications/mscutils/devmgmt/rsrc.rc @@ -33,3 +33,4 @@ IDB_EXIT BITMAP DISCARDABLE "res/exit.bmp" #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/mscutils/eventvwr/lang/zh-CN.rc b/base/applications/mscutils/eventvwr/lang/zh-CN.rc new file mode 100644 index 00000000000..fbcf63791e2 --- /dev/null +++ b/base/applications/mscutils/eventvwr/lang/zh-CN.rc @@ -0,0 +1,123 @@ +/* + * PROJECT: ReactOS Event Viewer + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/mscutils/eventvwr/lang/en-US.rc + * PURPOSE: Chinese Language File for ReactOS Event Viewer + * TRANSLATORS: Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDC_EVENTVWR MENU +BEGIN + POPUP "日志(&L)" + BEGIN + MENUITEM "应用程序日志(&A)", ID_LOG_APPLICATION + MENUITEM "安全日志(&S)", ID_LOG_SECURITY + MENUITEM "系统日志(&Y)", ID_LOG_SYSTEM + MENUITEM SEPARATOR + MENUITEM "退出(&X)", IDM_EXIT + END + POPUP "查看(&V)" + BEGIN + MENUITEM "刷新(&R)", IDM_REFRESH + END + MENUITEM "选项(&O)", ID_OPTIONS + POPUP "帮助(&H)" + BEGIN + MENUITEM "帮助内容(&E)", IDM_HELP + MENUITEM SEPARATOR + MENUITEM "关于... (&A)", IDM_ABOUT + END +END + +IDC_EVENTVWR ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + +IDD_ABOUTBOX DIALOGEX 0, 0, 230, 75 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_CAPTION | WS_SYSMENU +CAPTION "关于" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + ICON IDI_EVENTVWR,IDC_MYICON,14,9,21,20 + LTEXT "ReactOS 事件查看器 版本 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX + LTEXT "版权所有 (C) 2007 Marc Piulachs (marc.piulachs@codexchange.net)",IDC_STATIC,49,20,119,22 + DEFPUSHBUTTON "确定",IDOK,90,48,42,16,WS_GROUP +END + +IDD_PROGRESSBOX DIALOGEX 0, 0, 230, 40 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER +CAPTION "请稍候..." +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CTEXT "正在载入日志。请稍候...",IDC_STATIC,0,15,230,8,SS_NOPREFIX +END + +IDD_EVENTDETAILDIALOG DIALOGEX 0, 0, 276, 282 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTEXTHELP +CAPTION "事件详细信息" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "关闭(&C)",IDOK,12,258,50,14 + PUSHBUTTON "上一个(&P)",IDPREVIOUS,78,258,50,14 + PUSHBUTTON "下一个(&N)",IDNEXT,144,258,50,14 + PUSHBUTTON "帮助(&H)",IDHELP,210,258,50,14 + EDITTEXT IDC_EVENTTEXTEDIT,14,81,247,108,ES_MULTILINE | ES_READONLY + LTEXT "描述(&D):",IDC_STATIC,15,70,39,8 + LTEXT "日期:",IDC_STATIC,14,14,36,8 + LTEXT "Static",IDC_EVENTDATESTATIC,56,14,72,8 + LTEXT "时间:",IDC_STATIC,14,27,36,8 + LTEXT "Static",IDC_EVENTTIMESTATIC,56,27,72,8 + LTEXT "用户(&U):",IDC_STATIC,14,41,36,8 + LTEXT "Static",IDC_EVENTUSERSTATIC,56,41,72,8 + LTEXT "计算机(&C):",IDC_STATIC,14,54,36,8 + LTEXT "Static",IDC_EVENTCOMPUTERSTATIC,56,54,72,8 + LTEXT "事件 ID:",IDC_STATIC,133,15,36,8 + LTEXT "Static",IDC_EVENTIDSTATIC,175,15,87,8 + LTEXT "来源:",IDC_STATIC,133,28,36,8 + LTEXT "Static",IDC_EVENTSOURCESTATIC,175,28,87,8 + LTEXT "类型:",IDC_STATIC,133,42,36,8 + LTEXT "Static",IDC_EVENTTYPESTATIC,175,42,87,8 + LTEXT "分类:",IDC_STATIC,133,55,36,8 + LTEXT "Static",IDC_EVENTCATEGORYSTATIC,175,55,87,8 + EDITTEXT IDC_EVENTDATAEDIT,14,204,247,44,ES_MULTILINE | ES_READONLY + LTEXT "数据(&A)",IDC_STATIC,14,194,20,8 + CONTROL "字节(&B)",IDC_BYTESRADIO,"Button",BS_AUTORADIOBUTTON,39,194,34,10 + CONTROL "字(&W)",IDC_WORDRADIO,"Button",BS_AUTORADIOBUTTON,77,194,33,10 +END + +STRINGTABLE +BEGIN + IDS_APP_TITLE "事件查看器" + IDS_EVENTSTRINGIDNOTFOUND "来源 ( %s ) 中的事件 ID ( %lu ) 的描述无法找到。本地计算机可能没有显示来自远程计算机消息所必需的注册表信息或消息 DLL 文件。" + IDS_EVENTLOG_ERROR_TYPE "错误" + IDS_EVENTLOG_WARNING_TYPE "警告" + IDS_EVENTLOG_INFORMATION_TYPE "信息" + IDS_EVENTLOG_AUDIT_SUCCESS "审核成功" + IDS_EVENTLOG_AUDIT_FAILURE "审核失败" + IDS_EVENTLOG_SUCCESS "成功" + IDS_EVENTLOG_UNKNOWN_TYPE "未知事件" +END + +STRINGTABLE +BEGIN + IDS_COLUMNTYPE "类型" + IDS_COLUMNDATE "日期" + IDS_COLUMNTIME "时间" + IDS_COLUMNSOURCE "来源" + IDS_COLUMNCATEGORY "分类" + IDS_COLUMNEVENT "事件" + IDS_COLUMNUSER "用户" + IDS_COLUMNCOMPUTER "计算机" + IDS_COLUMNEVENTDATA "事件数据" +END + +STRINGTABLE +BEGIN + IDS_NONE "无" + IDS_NOT_AVAILABLE "不可用" +END diff --git a/base/applications/mscutils/eventvwr/rsrc.rc b/base/applications/mscutils/eventvwr/rsrc.rc index 1d5eeed9d28..512cd86e4ba 100644 --- a/base/applications/mscutils/eventvwr/rsrc.rc +++ b/base/applications/mscutils/eventvwr/rsrc.rc @@ -28,3 +28,4 @@ IDI_ERRORICON ICON "res/error.ico" #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/mscutils/servman/lang/zh-CN.rc b/base/applications/mscutils/servman/lang/zh-CN.rc new file mode 100644 index 00000000000..d86b98c082c --- /dev/null +++ b/base/applications/mscutils/servman/lang/zh-CN.rc @@ -0,0 +1,286 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDR_MAINMENU MENU +BEGIN + POPUP "文件(&F)" + BEGIN + MENUITEM "导出...", ID_EXPORT + MENUITEM SEPARATOR + MENUITEM "退出(&X)", ID_EXIT + END + POPUP "动作" + BEGIN + MENUITEM "连接到...", ID_CONNECT, GRAYED + MENUITEM SEPARATOR + MENUITEM "启动", ID_START, GRAYED + MENUITEM "停止", ID_STOP, GRAYED + MENUITEM "暂停", ID_PAUSE, GRAYED + MENUITEM "恢复", ID_RESUME, GRAYED + MENUITEM "重新启动", ID_RESTART, GRAYED + MENUITEM SEPARATOR + MENUITEM "刷新", ID_REFRESH + MENUITEM SEPARATOR + MENUITEM "编辑...", ID_EDIT, GRAYED + MENUITEM "创建...", ID_CREATE, GRAYED + MENUITEM "删除...", ID_DELETE, GRAYED + MENUITEM SEPARATOR + MENUITEM "属性...", ID_PROP, GRAYED + END + POPUP "查看" + BEGIN + MENUITEM "大图标", ID_VIEW_LARGE + MENUITEM "小图标", ID_VIEW_SMALL + MENUITEM "列表", ID_VIEW_LIST + MENUITEM "详细信息", ID_VIEW_DETAILS + MENUITEM SEPARATOR + MENUITEM "自定义...", ID_VIEW_CUST, GRAYED + END + POPUP "帮助" + BEGIN + MENUITEM "帮助内容", ID_HELP + MENUITEM "关于", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM "启动", ID_START, GRAYED + MENUITEM "停止", ID_STOP, GRAYED + MENUITEM "暂停", ID_PAUSE, GRAYED + MENUITEM "恢复", ID_RESUME, GRAYED + MENUITEM "重新启动", ID_RESTART, GRAYED + MENUITEM SEPARATOR + MENUITEM "刷新", ID_REFRESH + MENUITEM SEPARATOR + MENUITEM "编辑...", ID_EDIT, GRAYED + MENUITEM "删除...", ID_DELETE, GRAYED + MENUITEM SEPARATOR + MENUITEM "属性...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "帮助...", ID_HELP + END +END + +IDD_ABOUTBOX DIALOGEX 22,16,190,182 +CAPTION "关于服务管理器" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "服务管理器 v0.8\n版权所有 (C) 2005-2007\n作者 Ged Murphy (gedmurphy@reactos.org)", IDC_STATIC, 48, 7, 135, 30 + PUSHBUTTON "关闭", IDOK, 75, 162, 44, 15 + ICON IDI_SM_ICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 174, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + +IDD_DLG_GENERAL DIALOGEX 6, 6, 253, 232 +CAPTION "普通" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_THICKFRAME | WS_GROUP | WS_TABSTOP +BEGIN + LTEXT "", IDC_SERV_NAME, 70,11,176,11, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_DISP_NAME, 70, 29, 176, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_READONLY + EDITTEXT IDC_DESCRIPTION, 70, 46, 176, 24, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_MULTILINE | ES_READONLY + EDITTEXT IDC_EXEPATH, 6, 86, 240, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_READONLY + COMBOBOX IDC_START_TYPE, 70, 107, 176, 40, WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST + PUSHBUTTON "启动", IDC_START, 6, 155, 54, 15, WS_DISABLED + PUSHBUTTON "停止", IDC_STOP, 68, 155, 54, 15, WS_DISABLED + PUSHBUTTON "暂停", IDC_PAUSE , 130, 155, 54, 15, WS_DISABLED + PUSHBUTTON "恢复", IDC_RESUME, 192, 155, 54, 15, WS_DISABLED + LTEXT "服务名称:", IDC_STATIC, 4, 11, 53, 11 + LTEXT "显示名称:", IDC_STATIC, 4, 29, 53, 11 + LTEXT "描述:", IDC_STATIC, 4, 51, 53, 11 + LTEXT "可执行文件路径:", IDC_STATIC, 6, 73, 82, 9 + LTEXT "启动类型:", IDC_STATIC, 6, 108, 53, 11 + LTEXT "服务状态:", IDC_STATIC, 4, 138, 53, 11 + LTEXT "", IDC_SERV_STATUS, 70, 138, 176, 11, WS_CHILD | WS_VISIBLE + LTEXT "你可以在这里指定当你从这里启动该服务时所应用的参数。",IDC_STATIC, 6,177,240,15 + LTEXT "启动参数:", IDC_STATIC, 6, 200, 58, 11 + EDITTEXT IDC_START_PARAM, 68, 199, 178, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "编辑", IDC_EDIT, 192, 215, 54, 15, WS_DISABLED +END + +IDD_DLG_DEPEND DIALOGEX 6,6,253,225 +CAPTION "依赖" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_THICKFRAME | WS_GROUP | WS_TABSTOP +BEGIN + CONTROL "", IDC_DEPEND_TREE1, "SysTreeView32" , WS_BORDER | WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 70, 236, 68 + CONTROL "", IDC_DEPEND_TREE2, "SysTreeView32", WS_BORDER | WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 151, 234, 67 + LTEXT "一些服务依赖于其他服务,系统驱动程序和加载顺序组。如果一个系统组件被停止或者没有正确运行,被其依赖的服务也会被影响。", IDC_STATIC,8, 7, 238, 26 + LTEXT "这个服务依赖于以下的组件:", IDC_STATIC, 8, 57, 236, 9 + LTEXT "", IDC_DEPEND_SERVICE, 8, 38, 236, 13 +END + +IDD_DLG_CREATE DIALOGEX 6,6,225,209 +CAPTION "创建一个服务" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_THICKFRAME | WS_GROUP | WS_TABSTOP +BEGIN + EDITTEXT IDC_CREATE_SERVNAME, 72, 12, 150, 11, WS_CHILD | WS_VISIBLE | WS_EX_CLIENTEDGE + EDITTEXT IDC_CREATE_DISPNAME, 72, 31, 150, 11, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_CREATE_PATH, 10, 62, 210, 13, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_CREATE_DESC, 10, 97, 210, 48, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_CREATE_OPTIONS, 10, 162, 210, 13, WS_CHILD | WS_VISIBLE + LTEXT "*服务名称:", IDC_STATIC, 12, 12, 54, 9 + LTEXT "*显示名称:", IDC_STATIC, 12, 33, 54, 9 + LTEXT "*可执行文件路径:", IDC_STATIC, 10, 51, 68, 9 + LTEXT "描述:", IDC_STATIC, 12, 86, 44, 9 + PUSHBUTTON "确定", IDOK, 126, 192, 44, 13 + PUSHBUTTON "取消", IDCANCEL, 176, 192, 46, 13 + LTEXT "附加选项 (点击帮助以获得详细信息)", IDC_STATIC, 10, 151, 134, 9 + PUSHBUTTON "帮助", ID_CREATE_HELP, 10, 192, 44, 13 +END + +IDD_DLG_DELETE DIALOGEX 6,6,185,148 +CAPTION "删除一个服务" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME +BEGIN + ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22 + LTEXT "您确定要删除以下的服务吗?这个操作是不可撤消的!", IDC_STATIC, 50, 6, 125, 25 + LTEXT "服务名称:",IDC_STATIC, 6, 40, 80, 9 + LTEXT "", IDC_DEL_NAME, 15, 53, 160, 15 + EDITTEXT IDC_DEL_DESC, 6, 73, 174, 48, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_EX_STATICEDGE | ES_MULTILINE | ES_READONLY + PUSHBUTTON "是", IDOK, 26, 129, 54, 13 + DEFPUSHBUTTON "否", IDCANCEL, 102, 129, 54, 13 +END + +IDD_DLG_DEPEND_STOP DIALOGEX 6,6,240,148 +CAPTION "停止其他服务" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME +BEGIN + ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22 + LTEXT "", IDC_STOP_DEPENDS, 40, 8, 170, 25 + LISTBOX IDC_STOP_DEPENDS_LB, 15, 40, 210, 70, WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE | LBS_NOSEL + LTEXT "您确定要停止这些服务吗?",IDC_STATIC, 15, 110, 150, 10 + DEFPUSHBUTTON "是", IDOK, 60, 129, 54, 14 + PUSHBUTTON "否", IDCANCEL, 120, 129, 54, 14 +END + +IDD_DLG_HELP_OPTIONS DIALOGEX 6,6,200,150 +CAPTION "选项" +FONT 8, "MS Shell Dlg",0,0 +STYLE 0x10CF0000 +BEGIN + LTEXT "", IDC_CREATE_HELP, 6, 5, 200, 150 + PUSHBUTTON "确定", IDOK, 75, 130, 44, 13 +END + +IDD_DLG_PROGRESS DIALOGEX 6,6,255,89 +CAPTION "服务控制" +FONT 8, "MS Shell Dlg",0,0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_VISIBLE | DS_MODALFRAME +EXSTYLE WS_EX_TOOLWINDOW +BEGIN + CONTROL "", IDC_SERVCON_PROGRESS, "msctls_progress32", 0x50000000, 8, 46, 238, 13 + LTEXT "", IDC_SERVCON_INFO, 8, 5, 236, 11 + LTEXT "", IDC_SERVCON_NAME, 8, 25, 66, 11 + PUSHBUTTON "关闭(&C)", IDOK, 100, 70, 54, 13 +END + + + +STRINGTABLE DISCARDABLE +BEGIN + IDS_FIRSTCOLUMN "名称" + IDS_SECONDCOLUMN "描述" + IDS_THIRDCOLUMN "状态" + IDS_FOURTHCOLUMN "启动类型" + IDS_FITHCOLUMN "登录为" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_SERVICES_STARTED "已启动" + IDS_SERVICES_STOPPED "已停止" + IDS_SERVICES_AUTO "自动" + IDS_SERVICES_MAN "手动" + IDS_SERVICES_DIS "已禁用" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NUM_SERVICES "服务总数: %d" + IDS_STOP_DEPENDS "当 %s 停止时,这些服务也将被停止" + IDS_NO_DEPENDS "<没有依赖>" + IDS_LICENSE "这个程序是自由软件;你可以在自由软件基金会(FSF)的 GNU LGPL 协议下重新发布或修改它;也适用于这个协议的版本 2,或(在您看来)任何更新的版本。\r\n\r\n这个程序在希望其有用的愿望中发布,但没有任何保证;也不意味着性能保证或对某特定用途的适用性。请查看 GNU GPL 许可协议以了解更多细节。\r\n\r\n您应该已经收到了一份和这个程序一起的 GNU GPL 协议的副本;如果没有,请写信给自由软件基金会(FSF):51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_PROP "属性" + IDS_TOOLTIP_REFRESH "刷新" + IDS_TOOLTIP_EXPORT "导出列表" + IDS_TOOLTIP_CREATE "创建一个新的服务" + IDS_TOOLTIP_DELETE "删除一个已存在的服务" + IDS_TOOLTIP_START "启动服务" + IDS_TOOLTIP_STOP "停止服务" + IDS_TOOLTIP_PAUSE "暂停服务" + IDS_TOOLTIP_RESTART "重新启动服务" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_PROGRESS_INFO_START "ReactOS 正在尝试启动以下服务" + IDS_PROGRESS_INFO_STOP "ReactOS 正在尝试停止以下服务" + IDS_PROGRESS_INFO_PAUSE "ReactOS 正在尝试暂停以下服务" + IDS_PROGRESS_INFO_RESUME "ReactOS 正在尝试恢复以下服务" + IDS_CREATE_SUCCESS "成功创建服务" + IDS_DELETE_SUCCESS "成功删除服务" + IDS_CREATE_REQ "标记有\n星号 (*) 的字段是必需的" + IDS_DELETE_STOP "您必须在删除该服务前停止它!" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_HELP_OPTIONS "创建选项:\r\n注意:选项名包含了等号(=)。\r\n type= \r\n (default = own)\r\n start= \r\n (default = demand) \r\n error= \r\n (default = normal)\r\n group= \r\n tag= \r\n depend= \r\n obj= \r\n (default = LocalSystem)\r\n password= \r\n" +END + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_EXPORT " 将当前服务列表导出为一个文件。" + IDS_HINT_EXIT " 退出这个程序。" + + IDS_HINT_CONNECT " 管理一台不同的计算机。" + IDS_HINT_START " 启动选定的服务。" + IDS_HINT_STOP " 停止选定的服务。" + IDS_HINT_PAUSE " 暂停选定的服务。" + IDS_HINT_RESUME " 恢复选定的服务。" + IDS_HINT_RESTART " 停止然后启动选定的服务。" + IDS_HINT_REFRESH " 刷新服务列表。" + IDS_HINT_EDIT " 编辑选定服务的属性。" + IDS_HINT_CREATE " 创建一个新的服务。" + IDS_HINT_DELETE " 删除选定的服务。" + IDS_HINT_PROP " 为当前选择项目打开属性页。" + + IDS_HINT_LARGE " 用大图标显示条目。" + IDS_HINT_SMALL " 用小图标显示条目。" + IDS_HINT_LIST " 用列表显示条目。" + IDS_HINT_DETAILS " 在窗口中显示每个条目的信息。" + IDS_HINT_CUST " 自定义视图。" + + IDS_HINT_HELP " 显示帮助窗口。" + IDS_HINT_ABOUT " 关于 ReactOS 服务管理器。" + + IDS_HINT_SYS_RESTORE " 将这个窗口恢复到普通大小。" + IDS_HINT_SYS_MOVE " 移动这个窗口。" + IDS_HINT_SYS_SIZE " 调整这个窗口的大小。" + IDS_HINT_SYS_MINIMIZE " 将这个窗口折叠为一个图标。" + IDS_HINT_SYS_MAXIMIZE " 将这个窗口扩展到整个屏幕。" + IDS_HINT_SYS_CLOSE " 关闭这个窗口。" +END + +/* Application title */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ReactOS 服务管理器" +END diff --git a/base/applications/mscutils/servman/rsrc.rc b/base/applications/mscutils/servman/rsrc.rc index d414e7b356f..8ae670d6abb 100644 --- a/base/applications/mscutils/servman/rsrc.rc +++ b/base/applications/mscutils/servman/rsrc.rc @@ -41,3 +41,4 @@ IDI_DRIVER ICON "res/driver.ico" #include "lang/ro-RO.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/mspaint/CMakeLists.txt b/base/applications/mspaint/CMakeLists.txt index dee6aa9f405..38f0cc35de3 100644 --- a/base/applications/mspaint/CMakeLists.txt +++ b/base/applications/mspaint/CMakeLists.txt @@ -17,5 +17,6 @@ add_executable(mspaint rsrc.rc) set_module_type(mspaint win32gui) +add_pch(mspaint precomp.h) add_importlibs(mspaint comdlg32 shell32 user32 gdi32 advapi32 comctl32 msvcrt kernel32) add_cd_file(TARGET mspaint DESTINATION reactos/system32 FOR all) diff --git a/base/applications/mspaint/dialogs.c b/base/applications/mspaint/dialogs.c index bf3111b1bb7..0e843c5f7c2 100644 --- a/base/applications/mspaint/dialogs.c +++ b/base/applications/mspaint/dialogs.c @@ -8,10 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include -#include "definitions.h" -#include "globalvar.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/dib.c b/base/applications/mspaint/dib.c index 7c58f43c92d..4c1eaec7a2b 100644 --- a/base/applications/mspaint/dib.c +++ b/base/applications/mspaint/dib.c @@ -8,7 +8,7 @@ /* INCLUDES *********************************************************/ -#include +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/drawing.c b/base/applications/mspaint/drawing.c index e87b9bfe6ba..7a957baddf1 100644 --- a/base/applications/mspaint/drawing.c +++ b/base/applications/mspaint/drawing.c @@ -8,7 +8,7 @@ /* INCLUDES *********************************************************/ -#include +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/drawing.h b/base/applications/mspaint/drawing.h index b9f23ad4196..2c39ee9538d 100644 --- a/base/applications/mspaint/drawing.h +++ b/base/applications/mspaint/drawing.h @@ -26,7 +26,7 @@ void Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF void Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r); -void Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, int style); +void Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, COLORREF style); void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2); diff --git a/base/applications/mspaint/history.c b/base/applications/mspaint/history.c index e105dab0f0d..daf526c977d 100644 --- a/base/applications/mspaint/history.c +++ b/base/applications/mspaint/history.c @@ -8,10 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include "globalvar.h" -#include "dib.h" -#include "definitions.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/lang/zh-CN.rc b/base/applications/mspaint/lang/zh-CN.rc new file mode 100644 index 00000000000..2986838a5e5 --- /dev/null +++ b/base/applications/mspaint/lang/zh-CN.rc @@ -0,0 +1,206 @@ +/* + * PROJECT: PAINT for ReactOS + * LICENSE: unknown (LGPL assumed) + * FILE: base/applications/paint/lang/zh-CN.rc + * PURPOSE: Chinese Language resource file + * TRANSLATORS: Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +ID_MENU MENU +BEGIN + POPUP "文件(&F)" + BEGIN + MENUITEM "新建(&N)\tCtrl+N", IDM_FILENEW + MENUITEM "打开... (&O)\tCtrl+O", IDM_FILEOPEN + MENUITEM "保存(&S)\tCtrl+S", IDM_FILESAVE + MENUITEM "另存为... (&A)", IDM_FILESAVEAS + MENUITEM SEPARATOR + MENUITEM "保存为壁纸 (普通)", IDM_FILEASWALLPAPERPLANE + MENUITEM "保存为壁纸 (居中)", IDM_FILEASWALLPAPERCENTERED + MENUITEM "保存为壁纸 (拉伸)", IDM_FILEASWALLPAPERSTRETCHED + MENUITEM SEPARATOR + MENUITEM "退出(&Q)\tAlt+F4", IDM_FILEEXIT + END + + POPUP "编辑(&E)" + BEGIN + MENUITEM "撤销\tCtrl+Z", IDM_EDITUNDO + MENUITEM "重做\tCtrl+Y", IDM_EDITREDO + MENUITEM SEPARATOR + MENUITEM "剪切\tCtrl+X", IDM_EDITCUT + MENUITEM "复制\tCtrl+C", IDM_EDITCOPY + MENUITEM "粘贴\tCtrl+V", IDM_EDITPASTE + MENUITEM "删除选中区域\tDel", IDM_EDITDELETESELECTION + MENUITEM "反转选择", IDM_EDITINVERTSELECTION + MENUITEM "全部选择\tCtrl+A", IDM_EDITSELECTALL + MENUITEM SEPARATOR + MENUITEM "复制到...", IDM_EDITCOPYTO + MENUITEM "从...粘贴", IDM_EDITPASTEFROM + END + + POPUP "查看(&V)" + BEGIN + MENUITEM "工具箱\tCtrl+T", IDM_VIEWTOOLBOX, CHECKED + MENUITEM "调色板\tCtrl+L", IDM_VIEWCOLORPALETTE, CHECKED + MENUITEM "状态栏", IDM_VIEWSTATUSBAR, CHECKED + MENUITEM "文字工具栏", IDM_FORMATICONBAR, CHECKED, GRAYED + MENUITEM SEPARATOR + POPUP "缩放" + BEGIN + POPUP "用户定义" + BEGIN + MENUITEM "12.5%", IDM_VIEWZOOM125 + MENUITEM "25%", IDM_VIEWZOOM25 + MENUITEM "50%", IDM_VIEWZOOM50 + MENUITEM "100%", IDM_VIEWZOOM100 + MENUITEM "200%", IDM_VIEWZOOM200 + MENUITEM "400%", IDM_VIEWZOOM400 + MENUITEM "800%", IDM_VIEWZOOM800 + END + MENUITEM SEPARATOR + MENUITEM "显示网格\tCtrl+G", IDM_VIEWSHOWGRID + MENUITEM "显示缩略图", IDM_VIEWSHOWMINIATURE + END + MENUITEM "全屏显示\tCtrl+F", IDM_VIEWFULLSCREEN + END + + POPUP "图像(&I)" + BEGIN + MENUITEM "旋转/镜像...\tCtrl+R", IDM_IMAGEROTATEMIRROR + MENUITEM "改变大小...\tCtrl+W", IDM_IMAGECHANGESIZE + MENUITEM "剪裁", IDM_IMAGECROP + MENUITEM "颜色反转\tCtrl+I", IDM_IMAGEINVERTCOLORS + MENUITEM "属性...\tCtrl+E", IDM_IMAGEATTRIBUTES + MENUITEM "删除图像\tCtrl+Shft+N", IDM_IMAGEDELETEIMAGE + MENUITEM "不透明处理", IDM_IMAGEDRAWOPAQUE + END + + POPUP "颜色(&C)" + BEGIN + MENUITEM "编辑调色板...", IDM_COLORSEDITPALETTE + END + + POPUP "帮助(&?)" + BEGIN + MENUITEM "帮助主题", IDM_HELPHELPTOPICS + MENUITEM SEPARATOR + MENUITEM "信息", IDM_HELPINFO + END +END + +ID_ACCELERATORS ACCELERATORS +BEGIN + "^N", IDM_FILENEW + "^O", IDM_FILEOPEN + "^S", IDM_FILESAVE + "^Z", IDM_EDITUNDO + "^Y", IDM_EDITREDO + "^X", IDM_EDITCUT + "^C", IDM_EDITCOPY + "^V", IDM_EDITPASTE + VK_DELETE, IDM_EDITDELETESELECTION, VIRTKEY + "^A", IDM_EDITSELECTALL + "^T", IDM_VIEWTOOLBOX + "^L", IDM_VIEWCOLORPALETTE + "^G", IDM_VIEWSHOWGRID + "^F", IDM_VIEWFULLSCREEN + "^R", IDM_IMAGEROTATEMIRROR + "^W", IDM_IMAGECHANGESIZE + "^I", IDM_IMAGEINVERTCOLORS + "^E", IDM_IMAGEATTRIBUTES + "N", IDM_IMAGEDELETEIMAGE, CONTROL, SHIFT, VIRTKEY +END + +IDD_MIRRORROTATE DIALOGEX 100, 100, 180, 100 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +CAPTION "旋转和镜像图像" +BEGIN + GROUPBOX "旋转或镜像", IDD_MIRRORROTATEGROUP, 6, 6, 112, 86 + AUTORADIOBUTTON "水平镜像", IDD_MIRRORROTATERB1, 12, 18, 100, 10, WS_GROUP + AUTORADIOBUTTON "垂直镜像", IDD_MIRRORROTATERB2, 12, 30, 100, 10 + AUTORADIOBUTTON "旋转角度", IDD_MIRRORROTATERB3, 12, 42, 100, 10 + AUTORADIOBUTTON "90°", IDD_MIRRORROTATERB4, 42, 54, 50, 10, WS_GROUP | WS_DISABLED + AUTORADIOBUTTON "180°", IDD_MIRRORROTATERB5, 42, 66, 50, 10, WS_DISABLED + AUTORADIOBUTTON "270°", IDD_MIRRORROTATERB6, 42, 78, 50, 10, WS_DISABLED + DEFPUSHBUTTON "确定", IDOK, 125, 8, 48, 14 + PUSHBUTTON "取消", IDCANCEL, 125, 24, 48, 14 +END + +IDD_ATTRIBUTES DIALOGEX 100, 100, 210, 120 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +CAPTION "属性" +BEGIN + EDITTEXT IDD_ATTRIBUTESEDIT1, 40, 40, 35, 12 + EDITTEXT IDD_ATTRIBUTESEDIT2, 110, 40, 35, 12 + LTEXT "宽度:", IDD_ATTRIBUTESTEXT1, 10, 40, 30, 10 + LTEXT "高度:", IDD_ATTRIBUTESTEXT2, 80, 40, 30, 10 + LTEXT "文件日期:", IDD_ATTRIBUTESTEXT3, 10, 5, 60, 10 + LTEXT "文件大小:", IDD_ATTRIBUTESTEXT4, 10, 15, 60, 10 + LTEXT "分辨率:", IDD_ATTRIBUTESTEXT5, 10, 25, 60, 10 + LTEXT "不可用", IDD_ATTRIBUTESTEXT6, 60, 5, 90, 10 + LTEXT "不可用", IDD_ATTRIBUTESTEXT7, 60, 15, 90, 10 + LTEXT "不可用", IDD_ATTRIBUTESTEXT8, 60, 25, 90, 10 + GROUPBOX "单位", IDD_ATTRIBUTESGROUP1, 6, 57, 139, 27 + AUTORADIOBUTTON "英寸", IDD_ATTRIBUTESRB1, 12, 69, 35, 10, WS_GROUP + AUTORADIOBUTTON "厘米", IDD_ATTRIBUTESRB2, 52, 69, 35, 10 + AUTORADIOBUTTON "像素", IDD_ATTRIBUTESRB3, 92, 69, 35, 10 + GROUPBOX "颜色", IDD_ATTRIBUTESGROUP2, 6, 88, 139, 27 + AUTORADIOBUTTON "黑白", IDD_ATTRIBUTESRB4, 12, 100, 70, 10, WS_GROUP + AUTORADIOBUTTON "彩色", IDD_ATTRIBUTESRB5, 92, 100, 35, 10 + DEFPUSHBUTTON "确定", IDOK, 155, 8, 48, 14 + PUSHBUTTON "取消", IDCANCEL, 155, 24, 48, 14 + PUSHBUTTON "缺省", IDD_ATTRIBUTESSTANDARD, 155, 40, 48, 14 +END + +IDD_CHANGESIZE DIALOGEX 100, 100, 210, 80 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +CAPTION "改变大小" +BEGIN + GROUPBOX "改变大小", IDD_CHANGESIZEGROUP, 6, 6, 142, 66 + ICON IDI_HORZSTRETCH, IDD_CHANGESIZEICON1, 12, 18, 32, 32 + LTEXT "水平:", IDD_CHANGESIZETEXT1, 45, 24, 40, 10 + EDITTEXT IDD_CHANGESIZEEDIT1, 90, 23, 32, 12 + LTEXT "%", IDD_CHANGESIZETEXT2, 125, 24, 15, 10 + ICON IDI_VERTSTRETCH, IDD_CHANGESIZEICON2, 12, 43, 32, 32 + LTEXT "垂直:", IDD_CHANGESIZETEXT3, 45, 49, 40, 10 + EDITTEXT IDD_CHANGESIZEEDIT2, 90, 48, 32, 12 + LTEXT "%", IDD_CHANGESIZETEXT4, 125, 49, 15, 10 + DEFPUSHBUTTON "确定", IDOK, 155, 8, 48, 14 + PUSHBUTTON "取消", IDCANCEL, 155, 24, 48, 14 +END + +STRINGTABLE +BEGIN + IDS_PROGRAMNAME, "画图" + IDS_WINDOWTITLE, "%s - 画图" + IDS_INFOTITLE, "ReactOS 画图" + IDS_INFOTEXT, "ReactOS 画图是在 GNU LGPL 协议版本 3 下发布的 (详见 www.gnu.org)" + IDS_SAVEPROMPTTEXT, "您想把改变保存到 %s 吗?" + IDS_DEFAULTFILENAME, "未命名.bmp" + IDS_MINIATURETITLE, "缩略图" + IDS_TOOLTIP1, "自由选择" + IDS_TOOLTIP2, "选择" + IDS_TOOLTIP3, "橡皮擦" + IDS_TOOLTIP4, "填充" + IDS_TOOLTIP5, "取色" + IDS_TOOLTIP6, "缩放" + IDS_TOOLTIP7, "铅笔" + IDS_TOOLTIP8, "刷子" + IDS_TOOLTIP9, "喷枪" + IDS_TOOLTIP10, "文字" + IDS_TOOLTIP11, "直线" + IDS_TOOLTIP12, "贝塞尔曲线" + IDS_TOOLTIP13, "矩形" + IDS_TOOLTIP14, "多边形" + IDS_TOOLTIP15, "椭圆" + IDS_TOOLTIP16, "圆角矩形" + IDS_OPENFILTER, "位图文件 (*.bmp;*.dib)\1*.bmp;*.dib\1All files (*.*)\1*.*\1" + IDS_SAVEFILTER, "24 位位图文件 (*.bmp;*.dib)\1*.bmp;*.dib\1" + IDS_FILESIZE, "%d 字节" + IDS_PRINTRES, "%d x %d 像素每米" +END diff --git a/base/applications/mspaint/main.c b/base/applications/mspaint/main.c index a103af9932c..cf15d3235fd 100644 --- a/base/applications/mspaint/main.c +++ b/base/applications/mspaint/main.c @@ -8,25 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include -#include -#include -#include -#include "definitions.h" - -#include "drawing.h" -#include "dib.h" - -#include "globalvar.h" -#include "history.h" -#include "mouse.h" - -#include "winproc.h" -#include "palette.h" -#include "toolsettings.h" -#include "selection.h" -#include "sizebox.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/mouse.c b/base/applications/mspaint/mouse.c index 26d3ffb5a96..84909fb1f9b 100644 --- a/base/applications/mspaint/mouse.c +++ b/base/applications/mspaint/mouse.c @@ -8,10 +8,7 @@ /* INCLUDES *********************************************************/ -#include "globalvar.h" -#include "dib.h" -#include "drawing.h" -#include "history.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/palette.c b/base/applications/mspaint/palette.c index cc68516e2a3..2626971ec5a 100644 --- a/base/applications/mspaint/palette.c +++ b/base/applications/mspaint/palette.c @@ -8,8 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include "globalvar.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/precomp.h b/base/applications/mspaint/precomp.h new file mode 100644 index 00000000000..cce714ad707 --- /dev/null +++ b/base/applications/mspaint/precomp.h @@ -0,0 +1,20 @@ + +#include +#include +#include +#include +#include + +#include "definitions.h" +#include "drawing.h" +#include "dib.h" +#include "globalvar.h" +#include "history.h" +#include "mouse.h" +#include "winproc.h" +#include "palette.h" +#include "toolsettings.h" +#include "selection.h" +#include "sizebox.h" +#include "dialogs.h" +#include "registry.h" \ No newline at end of file diff --git a/base/applications/mspaint/registry.c b/base/applications/mspaint/registry.c index 6f4e8e53a64..9da17c9a3f7 100644 --- a/base/applications/mspaint/registry.c +++ b/base/applications/mspaint/registry.c @@ -8,8 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/rsrc.rc b/base/applications/mspaint/rsrc.rc index 882a7eadcf8..d144db465e6 100644 --- a/base/applications/mspaint/rsrc.rc +++ b/base/applications/mspaint/rsrc.rc @@ -39,3 +39,4 @@ #include "lang/ro-RO.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/mspaint/selection.c b/base/applications/mspaint/selection.c index 03d7a18f75b..8a77b51c9f6 100644 --- a/base/applications/mspaint/selection.c +++ b/base/applications/mspaint/selection.c @@ -8,14 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include -#include -#include "globalvar.h" -#include "drawing.h" -#include "history.h" -#include "mouse.h" -#include "dib.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/sizebox.c b/base/applications/mspaint/sizebox.c index 9fa05ec8bed..728bd63a47f 100644 --- a/base/applications/mspaint/sizebox.c +++ b/base/applications/mspaint/sizebox.c @@ -8,11 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include -#include -#include "globalvar.h" -#include "history.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/toolsettings.c b/base/applications/mspaint/toolsettings.c index 2e5cd67661d..2ba81c7e68d 100644 --- a/base/applications/mspaint/toolsettings.c +++ b/base/applications/mspaint/toolsettings.c @@ -8,11 +8,7 @@ /* INCLUDES *********************************************************/ -#include -#include -#include "globalvar.h" -#include "drawing.h" -#include "winproc.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mspaint/winproc.c b/base/applications/mspaint/winproc.c index 8184302013f..391107499b7 100644 --- a/base/applications/mspaint/winproc.c +++ b/base/applications/mspaint/winproc.c @@ -9,19 +9,8 @@ /* INCLUDES *********************************************************/ -#include -#include //#include -#include -#include -#include "definitions.h" -#include "globalvar.h" -#include "dialogs.h" -#include "dib.h" -#include "drawing.h" -#include "history.h" -#include "mouse.h" -#include "registry.h" +#include "precomp.h" /* FUNCTIONS ********************************************************/ diff --git a/base/applications/mstsc/lang/zh-CN.rc b/base/applications/mstsc/lang/zh-CN.rc new file mode 100644 index 00000000000..b9db57a076a --- /dev/null +++ b/base/applications/mstsc/lang/zh-CN.rc @@ -0,0 +1,67 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDD_GENERAL DIALOGEX 0, 0, 242, 175 +STYLE DS_SHELLFONT | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "登录设置",IDC_STATIC,7,7,228,89 + GROUPBOX "连接设置",IDC_STATIC,7,103,228,65 + ICON "", IDC_LOGONICON, 15,19,20,20 + LTEXT "输入服务器地址",IDC_STATIC,47,24,81,8 + LTEXT "服务器:",IDC_STATIC,47,41,25,8 + LTEXT "用户名:",IDC_STATIC,47,58,38,8 + COMBOBOX IDC_SERVERCOMBO,79,39,141,150,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "保存",IDC_SAVE,67,139,50,14 + PUSHBUTTON "另存为...",IDC_SAVEAS,123,139,50,14 + PUSHBUTTON "打开...",IDC_OPEN,177,139,50,14 + ICON "", IDC_CONNICON, 16,114,20,20 + LTEXT "保存当前连接设置或打开一个已有的配置",IDC_STATIC,50,115,172,20 +END + +IDD_DISPLAY DIALOGEX 0, 0, 242, 175 +STYLE DS_SHELLFONT | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "远程桌面大小",IDC_STATIC,7,7,228,68 + GROUPBOX "颜色",IDC_STATIC,7,83,228,85 + ICON "", IDC_REMICON, 15,19,20,20 + ICON "", IDC_COLORSICON, 15,98,20,20 + LTEXT "为您的远程桌面设置屏幕大小。将这个滑块向右拉远以启用全屏。",IDC_STATIC,53,22,175,21 + CONTROL "", IDC_GEOSLIDER, "msctls_trackbar32", TBS_AUTOTICKS | WS_TABSTOP, 56, 42, 124, 17 + COMBOBOX IDC_BPPCOMBO,56,102,128,80, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + CONTROL "",IDC_COLORIMAGE,"Static",SS_OWNERDRAW | SS_SUNKEN, 56,121,127,10 + LTEXT "注意:远程计算机上的设置可能会覆盖这个设置。",IDC_STATIC,56,143,165,18 + LTEXT "更少",IDC_STATIC,35,42,15,8 + LTEXT "更多",IDC_STATIC,189,42,17,8 + LTEXT "", IDC_SETTINGS_RESOLUTION_TEXT, 56, 62, 120, 10, SS_CENTER +END + +IDD_CONNECTDIALOG DIALOGEX 0, 0, 260, 262 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "远程桌面连接" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "连接",IDOK,147,245,50,14 + PUSHBUTTON "取消",IDCANCEL,203,245,50,14 + CONTROL "",IDC_TAB,"SysTabControl32",0x0,7,50,246,190 +END + + +STRINGTABLE +BEGIN + IDS_TAB_GENERAL "普通" + IDS_TAB_DISPLAY "显示" + IDS_256COLORS "256 色" + IDS_HIGHCOLOR15 "32,768 色 (15 位)" + IDS_HIGHCOLOR16 "65,536 色 (16 位)" + IDS_HIGHCOLOR24 "16,777,216 色 (24 位)" + IDS_PIXEL "%lux%lu 像素" + IDS_FULLSCREEN "全屏" + IDS_BROWSESERVER "<浏览更多...>" + IDS_HEADERTEXT1 "远程桌面" + IDS_HEADERTEXT2 "连接" +END diff --git a/base/applications/mstsc/rsrc.rc b/base/applications/mstsc/rsrc.rc index 0de087fb8f3..7dc783896ee 100644 --- a/base/applications/mstsc/rsrc.rc +++ b/base/applications/mstsc/rsrc.rc @@ -32,3 +32,4 @@ IDB_SPECT BITMAP "res/spectrum.bmp" #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/network/finger/CMakeLists.txt b/base/applications/network/finger/CMakeLists.txt index e6156a14af7..dd5444909e0 100644 --- a/base/applications/network/finger/CMakeLists.txt +++ b/base/applications/network/finger/CMakeLists.txt @@ -9,5 +9,6 @@ add_executable(finger finger.rc) set_module_type(finger win32cui) +add_pch(finger precomp.h) add_importlibs(finger ws2_32 msvcrt kernel32) add_cd_file(TARGET finger DESTINATION reactos/system32 FOR all) diff --git a/base/applications/network/finger/err.c b/base/applications/network/finger/err.c index 8f1cc4ed030..ff6ccd7ddbf 100644 --- a/base/applications/network/finger/err.c +++ b/base/applications/network/finger/err.c @@ -35,17 +35,7 @@ static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ -#include "err.h" -#include -#include -#include -#include - -#ifdef __STDC__ -#include -#else -#include -#endif +#include "precomp.h" extern char *__progname; /* Program name, from crt0. */ diff --git a/base/applications/network/finger/finger.c b/base/applications/network/finger/finger.c index ddb4bebaf1d..82abc45a76a 100644 --- a/base/applications/network/finger/finger.c +++ b/base/applications/network/finger/finger.c @@ -54,17 +54,7 @@ * mail info, and .plan/.project files. */ -#include -#include "err.h" -#include -#include -#include -#include -#include -#include - -#include "various.h" -#include "getopt.h" +#include "precomp.h" char *__progname; diff --git a/base/applications/network/finger/getopt.c b/base/applications/network/finger/getopt.c index ae5cc0985cc..ec49191e0d6 100644 --- a/base/applications/network/finger/getopt.c +++ b/base/applications/network/finger/getopt.c @@ -38,11 +38,7 @@ static char sccsid[] = "@(#)getopt.c 4.13 (Berkeley) 2/23/91"; #endif /* LIBC_SCCS and not lint */ -#include -#include -#include - -#include "getopt.h" +#include "precomp.h" /* * get option letter from argument vector diff --git a/base/applications/network/finger/net.c b/base/applications/network/finger/net.c index 7f932ef2b5d..1e004359923 100644 --- a/base/applications/network/finger/net.c +++ b/base/applications/network/finger/net.c @@ -34,12 +34,7 @@ * SUCH DAMAGE. */ -#include -#include -#include -#include - -#include "various.h" +#include "precomp.h" void netfinger(char *name) diff --git a/base/applications/network/finger/precomp.h b/base/applications/network/finger/precomp.h new file mode 100644 index 00000000000..53de144bbed --- /dev/null +++ b/base/applications/network/finger/precomp.h @@ -0,0 +1,19 @@ + +#include +#include "err.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#else +#include +#endif + +#include "various.h" +#include "getopt.h" diff --git a/base/applications/network/ftp/CMakeLists.txt b/base/applications/network/ftp/CMakeLists.txt index 902f9de6ea7..48988202a2a 100644 --- a/base/applications/network/ftp/CMakeLists.txt +++ b/base/applications/network/ftp/CMakeLists.txt @@ -13,6 +13,7 @@ add_executable(ftp set_module_type(ftp win32cui) add_importlibs(ftp ws2_32 iphlpapi msvcrt kernel32) +add_pch(ftp precomp.h) if(MSVC) target_link_libraries(ftp oldnames) diff --git a/base/applications/network/ftp/cmds.c b/base/applications/network/ftp/cmds.c index 91b3bc48d5e..b4f9912bf6b 100644 --- a/base/applications/network/ftp/cmds.c +++ b/base/applications/network/ftp/cmds.c @@ -24,26 +24,8 @@ static char sccsid[] = "@(#)cmds.c 5.18 (Berkeley) 4/20/89"; */ //#include //#include -#include -#ifndef _WIN32 -#include -#include -#include -#include -#else -#include -#endif - -#include -#include -#include -#include -#include -#include -#include "ftp_var.h" -#include "pathnames.h" -#include "prototypes.h" +#include "precomp.h" extern char *globerr; extern char home[]; diff --git a/base/applications/network/ftp/cmdtab.c b/base/applications/network/ftp/cmdtab.c index 5c336526591..3dafb9c525b 100644 --- a/base/applications/network/ftp/cmdtab.c +++ b/base/applications/network/ftp/cmdtab.c @@ -19,7 +19,7 @@ static char sccsid[] = "@(#)cmdtab.c 5.9 (Berkeley) 3/21/89"; #endif /* not lint */ -#include "ftp_var.h" +#include "precomp.h" /* * User FTP -- Command Tables. diff --git a/base/applications/network/ftp/domacro.c b/base/applications/network/ftp/domacro.c index fc96ad76288..504f354dbcf 100644 --- a/base/applications/network/ftp/domacro.c +++ b/base/applications/network/ftp/domacro.c @@ -19,13 +19,8 @@ static char sccsid[] = "@(#)domacro.c 1.6 (Berkeley) 2/28/89"; #endif /* not lint */ -#include "ftp_var.h" -#include "prototypes.h" - -#include -#include +#include "precomp.h" //#include -#include //#include void domacro(int argc, const char *argv[]) diff --git a/base/applications/network/ftp/fake.c b/base/applications/network/ftp/fake.c index 5f4bfc88f83..17b50308640 100644 --- a/base/applications/network/ftp/fake.c +++ b/base/applications/network/ftp/fake.c @@ -1,8 +1,4 @@ -#include -#include -#include -#include "fake.h" -#include "prototypes.h" +#include "precomp.h" #define MAX_ASCII 100 diff --git a/base/applications/network/ftp/ftp.c b/base/applications/network/ftp/ftp.c index 9d0da1c4a73..407a3d31651 100644 --- a/base/applications/network/ftp/ftp.c +++ b/base/applications/network/ftp/ftp.c @@ -21,33 +21,9 @@ #ifndef lint static char sccsid[] = "@(#)ftp.c 5.28 (Berkeley) 4/20/89"; #endif /* not lint */ -#include -#include +#include "precomp.h" -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#endif - -#include -#include -#include -#include - -#include "ftp_var.h" -#include "prototypes.h" #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif diff --git a/base/applications/network/ftp/main.c b/base/applications/network/ftp/main.c index 5843096df99..db4859f3987 100644 --- a/base/applications/network/ftp/main.c +++ b/base/applications/network/ftp/main.c @@ -28,26 +28,7 @@ static char sccsid[] = "@(#)main.c based on 5.13 (Berkeley) 3/14/89"; /* * FTP User Program -- Command Interface. */ -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#endif -#include "ftp_var.h" -#include "prototypes.h" -#include - -#include -#include - -#include -#include -#include -#include - +#include "precomp.h" #if defined(sun) && !defined(FD_SET) typedef int uid_t; diff --git a/base/applications/network/ftp/precomp.h b/base/applications/network/ftp/precomp.h new file mode 100644 index 00000000000..df38d0a10a4 --- /dev/null +++ b/base/applications/network/ftp/precomp.h @@ -0,0 +1,36 @@ + +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ftp_var.h" +#include "pathnames.h" +#include "prototypes.h" + +#include "fake.h" + +#include diff --git a/base/applications/network/ftp/ruserpass.c b/base/applications/network/ftp/ruserpass.c index 618147e8d9a..248814b567c 100644 --- a/base/applications/network/ftp/ruserpass.c +++ b/base/applications/network/ftp/ruserpass.c @@ -19,15 +19,8 @@ static char sccsid[] = "@(#)ruserpass.c 5.1 (Berkeley) 3/1/89"; #endif /* not lint */ -#include -#include +#include "precomp.h" //#include -#include -#include -#include -#include "ftp_var.h" -#include "prototypes.h" -#include struct utmp *getutmp(); static FILE *cfile; diff --git a/base/applications/network/ipconfig/ipconfig.rc b/base/applications/network/ipconfig/ipconfig.rc index 58af6e0ff91..a27be7404d7 100644 --- a/base/applications/network/ipconfig/ipconfig.rc +++ b/base/applications/network/ipconfig/ipconfig.rc @@ -24,3 +24,4 @@ #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/network/ipconfig/lang/zh-CN.rc b/base/applications/network/ipconfig/lang/zh-CN.rc new file mode 100644 index 00000000000..2b28bc09c25 --- /dev/null +++ b/base/applications/network/ipconfig/lang/zh-CN.rc @@ -0,0 +1,69 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + IDS_BCAST "广播" + IDS_P2P "点对点" + IDS_MIXED "混合" + IDS_HYBRID "混杂" + IDS_UNKNOWN "未知" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_OTHER "其他类型的适配器" + IDS_ETH "以太网适配器" + IDS_TOKEN "令牌环适配器" + IDS_FDDI "FDDI 适配器" + IDS_PPP "PPP 适配器" + IDS_LOOP "本地环回适配器" + IDS_SLIP "SLIP 适配器" +END + +STRINGTABLE DISCARDABLE +BEGIN +/* Please keep the spacing/formatting as per En.rc when translating */ + IDS_USAGE + "\用法:\n \ + ipconfig [/? | /all | /renew [适配器] | /release [适配器] |\n \ + /flushdns | /displaydns | /registerdns |\n \ + /showclassid 适配器 |\n \ + /setclassid 适配器 [ç±»ID] ]\n \ + \n \ + 其中\n \ + 适配器 连接名称\n \ + (通配符 * 和 ? 是被允许的,参见示例)\n \ + \n \ + 选项:\n \ + /? 显示这个帮助信息。\n \ + /all 显示完全的配置信息。\n \ + /release 释放指定适配器的 IP 地址。\n \ + /renew 更新指定适配器的 IP 地址。\n \ + /flushdns 清空 DNS 缓存。\n \ + /registerdns 刷新所有 DHCP 租约并且重新注册 DNS 名称。\n \ + /displaydns 显示 DNS 缓存中的内容。\n \ + /showclassid 显示所有被指定适配器允许的 DHCP ç±» ID。\n \ + /setclassid 修改 DHCP ç±» ID。\n \ + \n \ + 该程序的默认行为是仅显示每个绑定到 TCP/IP 的适配器的 IP 地址,子网掩码和\n \ + 默认网关。\n \ + \n \ + 对于释放和更新操作,如果没有指定适配器名称,那么所有绑定到 TCP/IP 的适配器\n \ + 的 IP 地址将会被释放或更新。\n \ + \n \ + 对于设置类 ID 操作,如果没有指定类 ID,那么类 ID 将被删除。\n \ + \n \ + 示例:\n \ + > ipconfig ... 显示信息。\n \ + > ipconfig /all ... 显示详细信息\n \ + > ipconfig /renew ... 更新所有适配器\n \ + > ipconfig /renew EL* ... 更新所有名称以 EL 开头\n \ + 的连接\n \ + > ipconfig /release *Con* ... 释放所有匹配的连接,\n \ + 如 ""Local Area Connection 1"" 或\n \ + ""Local Area Connection 2""\n" +END diff --git a/base/applications/network/net/CMakeLists.txt b/base/applications/network/net/CMakeLists.txt index 215d6a58d35..668c18a4ec0 100644 --- a/base/applications/network/net/CMakeLists.txt +++ b/base/applications/network/net/CMakeLists.txt @@ -11,5 +11,6 @@ list(APPEND SOURCE add_executable(net ${SOURCE}) set_module_type(net win32cui) +add_pch(net net.h) add_importlibs(net ws2_32 msvcrt kernel32) add_cd_file(TARGET net DESTINATION reactos/system32 FOR all) diff --git a/base/applications/network/nslookup/CMakeLists.txt b/base/applications/network/nslookup/CMakeLists.txt index bc6fe21eaa0..6a6b59fce1b 100644 --- a/base/applications/network/nslookup/CMakeLists.txt +++ b/base/applications/network/nslookup/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(nslookup utility.c nslookup.rc) +add_pch(nslookup nslookup.h) set_module_type(nslookup win32cui) add_importlibs(nslookup user32 ws2_32 snmpapi iphlpapi msvcrt kernel32) add_cd_file(TARGET nslookup DESTINATION reactos/system32 FOR all) diff --git a/base/applications/network/nslookup/nslookup.c b/base/applications/network/nslookup/nslookup.c index 11b1e91040b..fc94274da00 100644 --- a/base/applications/network/nslookup/nslookup.c +++ b/base/applications/network/nslookup/nslookup.c @@ -6,13 +6,6 @@ * COPYRIGHT: Copyright 2009 Lucas Suggs */ -#include -#include -#include -#include -#include -#include -#include #include "nslookup.h" STATE State; diff --git a/base/applications/network/nslookup/nslookup.h b/base/applications/network/nslookup/nslookup.h index 51ff023001b..06cd69cc7f5 100644 --- a/base/applications/network/nslookup/nslookup.h +++ b/base/applications/network/nslookup/nslookup.h @@ -1,3 +1,11 @@ +#include +#include +#include +#include +#include +#include +#include + #define TypeA "A" #define TypeAAAA "AAAA" #define TypeBoth "A+AAAA" diff --git a/base/applications/network/nslookup/utility.c b/base/applications/network/nslookup/utility.c index 50e8cc12d29..3b8d17f92b1 100644 --- a/base/applications/network/nslookup/utility.c +++ b/base/applications/network/nslookup/utility.c @@ -6,9 +6,6 @@ * COPYRIGHT: Copyright 2009 Lucas Suggs */ -#include -#include -#include #include "nslookup.h" BOOL SendRequest( PCHAR pInBuffer, diff --git a/base/applications/network/ping/lang/zh-CN.rc b/base/applications/network/ping/lang/zh-CN.rc new file mode 100644 index 00000000000..295942cb100 --- /dev/null +++ b/base/applications/network/ping/lang/zh-CN.rc @@ -0,0 +1,39 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + IDS_USAGE "\用法:ping [-t] [-n 次数] [-l 大小] [-w 超时] 目标主机\n\n\ +选项:\n\ + -t 不停呼叫指定的主机直到被终止。\n\ + 要停止 - 按下 Ctrl-C。\n\ + -n 次数 发送回响包的次数。\n\ + -l 大小 发送包的大小。\n\ + -w 超时 等待每个回复的时间(毫秒)。\n\n\0" + + IDS_PING_WITH_BYTES "\n正在呼叫 %1 [%2] ,数据包大小 %3!d! 字节:\n\n\0" + IDS_PING_STATISTICS "\n%1 的呼叫统计:\n\0" + IDS_PACKETS_SENT_RECEIVED_LOST " 数据包:发送个数 = %1!d!,接收个数 = %2!d!,丢失个数 = %3!d! (丢失率 %4!d!%%),\n\0" + IDS_APPROXIMATE_ROUND_TRIP "近似来回所需时间(毫秒):\n\0" + IDS_MIN_MAX_AVERAGE " 最小值 = %1, 最大值 = %2, 平均值 = %3\n\0" + IDS_NOT_ENOUGH_RESOURCES "空闲资源不足。\n\0" + IDS_UNKNOWN_HOST "未知主机 %1。\n\0" + IDS_SETSOCKOPT_FAILED "setsockopt 失败 (%1!d!)。\n\0" + IDS_COULD_NOT_CREATE_SOCKET "不能创建套接字 (#%1!d!)。\n\0" + IDS_COULD_NOT_INIT_WINSOCK "不能初始化 winsock dll。\n\0" + IDS_DEST_MUST_BE_SPECIFIED "目标主机的名称或 IP 地址必须被指定。\n\0" + IDS_BAD_PARAMETER "错误参数 %1。\n\0" + IDS_BAD_OPTION_FORMAT "错误选项格式 %1。\n\0" + IDS_BAD_OPTION "错误选项 %1。\n\0" + IDS_BAD_VALUE_OPTION_L "-l 选项的值无效,有效的范围是从 0 到 %1!d!。\n\0" + IDS_REPLY_FROM "来自 %1 的回复:字节数=%2!d! 时间%3%4 TTL=%5!d!\n\0" + IDS_DEST_UNREACHABLE "目标主机不可到达。\n\0" + IDS_COULD_NOT_TRANSMIT "无法发送数据 (%1!d!)。\n\0" + IDS_COULD_NOT_RECV "无法接收数据 (%1!d!)。\n\0" + IDS_REQUEST_TIMEOUT "请求超时。\n\0" + IDS_MS "ms\0" + IDS_1MS "1ms\0" +END diff --git a/base/applications/network/ping/ping.rc b/base/applications/network/ping/ping.rc index 6972ec44b37..fcfe015c956 100644 --- a/base/applications/network/ping/ping.rc +++ b/base/applications/network/ping/ping.rc @@ -19,3 +19,4 @@ #pragma code_page(65001) #include "lang/pl-PL.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/network/telnet/CMakeLists.txt b/base/applications/network/telnet/CMakeLists.txt index 51c76fa0ebc..74f41d0ea5b 100644 --- a/base/applications/network/telnet/CMakeLists.txt +++ b/base/applications/network/telnet/CMakeLists.txt @@ -26,5 +26,6 @@ add_executable(telnet telnet.rc) set_module_type(telnet win32cui) +add_pch(telnet src/precomp.h) add_importlibs(telnet ws2_32 user32 msvcrt kernel32) add_cd_file(TARGET telnet DESTINATION reactos/system32 FOR all) diff --git a/base/applications/network/telnet/src/ansiprsr.cpp b/base/applications/network/telnet/src/ansiprsr.cpp index e24f44fea35..1263733e988 100644 --- a/base/applications/network/telnet/src/ansiprsr.cpp +++ b/base/applications/network/telnet/src/ansiprsr.cpp @@ -50,8 +50,7 @@ /////////////////////////////////////////////////////////////////////////////// //#include -#include -#include "ansiprsr.h" +#include "precomp.h" const int ANSIColors[] = {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE}; diff --git a/base/applications/network/telnet/src/keytrans.cpp b/base/applications/network/telnet/src/keytrans.cpp index 0647c8e636c..e385d11c512 100644 --- a/base/applications/network/telnet/src/keytrans.cpp +++ b/base/applications/network/telnet/src/keytrans.cpp @@ -44,21 +44,7 @@ // DeleteKeyDef : Deletes a key def from the list // /////////////////////////////////////////////////////////////////// -#include - -// changed to make work with VC++ (Paul Brannan 5/25/98) -// FIX ME !!! Ioannou: This must be __BORLANDC__ && VERSION < 5 -// but what is the directive for Borland version ???? -// FIXED Sept. 31, 2000 (Bernard Badger) -// -#if defined(__BORLANDC__) && (__BORLANDC < 0x0500) -#include -#else -#include -#endif - -#include "keytrans.h" -#include "tnerror.h" +#include "precomp.h" ///////////////////////////////////////////////////////////// // class KeyTranslator // diff --git a/base/applications/network/telnet/src/precomp.h b/base/applications/network/telnet/src/precomp.h new file mode 100644 index 00000000000..373e06f5c44 --- /dev/null +++ b/base/applications/network/telnet/src/precomp.h @@ -0,0 +1,47 @@ +#include "ansiprsr.h" + +#if defined(__BORLANDC__) && (__BORLANDC < 0x0500) +#include +#else +#include +#endif + +#ifdef __BORLANDC__ +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "keytrans.h" +#include "tnerror.h" +#include "tcharmap.h" +#include "tnconfig.h" +#include "tconsole.h" +#include "tkeydef.h" +#include "tkeymap.h" +#include "tmapldr.h" +#include "tmouse.h" +#include "tnclass.h" +#include "tnmisc.h" +#include "tnclip.h" +#include "tncon.h" +#include "ttelhndl.h" +#include "tnetwork.h" +#include "tnmain.h" +#include "tscript.h" +#include "tscroll.h" +#include "telnet.h" +#include "tparams.h" diff --git a/base/applications/network/telnet/src/tcharmap.cpp b/base/applications/network/telnet/src/tcharmap.cpp index 23564c8b872..4bc461e8279 100644 --- a/base/applications/network/telnet/src/tcharmap.cpp +++ b/base/applications/network/telnet/src/tcharmap.cpp @@ -28,9 +28,7 @@ // Written by Paul Brannan // Last modified 7/12/98 -#include -#include "tcharmap.h" -#include "tnconfig.h" +#include "precomp.h" // map B (US ASCII) // this maps each character to itself diff --git a/base/applications/network/telnet/src/tconsole.cpp b/base/applications/network/telnet/src/tconsole.cpp index ec866816c0d..97449aa04ca 100644 --- a/base/applications/network/telnet/src/tconsole.cpp +++ b/base/applications/network/telnet/src/tconsole.cpp @@ -46,8 +46,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include "tconsole.h" +#include "precomp.h" // argsused doesn't work on MSVC++ #ifdef __BORLANDC__ diff --git a/base/applications/network/telnet/src/tkeydef.cpp b/base/applications/network/telnet/src/tkeydef.cpp index e1803271826..2d3e2120a08 100644 --- a/base/applications/network/telnet/src/tkeydef.cpp +++ b/base/applications/network/telnet/src/tkeydef.cpp @@ -29,8 +29,7 @@ // originally part of KeyTrans.cpp // ///////////////////////////////////////////////////////// -#include "tkeydef.h" -#include +#include "precomp.h" // This class did not properly release memory before, and a buffer overrun // was apparent in operator=(char*). Fixed. (Paul Brannan Feb. 4, 1999) diff --git a/base/applications/network/telnet/src/tkeymap.cpp b/base/applications/network/telnet/src/tkeymap.cpp index e1730f5a8bf..c62020a6672 100644 --- a/base/applications/network/telnet/src/tkeymap.cpp +++ b/base/applications/network/telnet/src/tkeymap.cpp @@ -29,7 +29,7 @@ // originally part of KeyTrans.cpp // ///////////////////////////////////////////////////////// -#include "tkeymap.h" +#include "precomp.h" KeyMap::KeyMap(DWORD state, DWORD code): map(0,0,sizeof(TKeyDef)), key(NULL,state,code) {}; diff --git a/base/applications/network/telnet/src/tmapldr.cpp b/base/applications/network/telnet/src/tmapldr.cpp index 18e2d621a60..3680645db11 100644 --- a/base/applications/network/telnet/src/tmapldr.cpp +++ b/base/applications/network/telnet/src/tmapldr.cpp @@ -29,15 +29,7 @@ // originally part of KeyTrans.cpp // ///////////////////////////////////////////////////////// -#include "tmapldr.h" -#include "tnconfig.h" - -#ifdef __BORLANDC__ -#include -#else -#include -#include -#endif +#include "precomp.h" // It's probably a good idea to turn off the "identifier was truncated" warning // in MSVC (Paul Brannan 5/25/98) diff --git a/base/applications/network/telnet/src/tmouse.cpp b/base/applications/network/telnet/src/tmouse.cpp index 322965bc5a3..317289dcf95 100644 --- a/base/applications/network/telnet/src/tmouse.cpp +++ b/base/applications/network/telnet/src/tmouse.cpp @@ -28,8 +28,7 @@ // Written by Paul Brannan // Last modified August 30, 1998 -#include "tmouse.h" -#include "tconsole.h" +#include "precomp.h" TMouse::TMouse(Tnclip &RefClipboard): Clipboard(RefClipboard) { hConsole = GetStdHandle(STD_INPUT_HANDLE); diff --git a/base/applications/network/telnet/src/tnclass.cpp b/base/applications/network/telnet/src/tnclass.cpp index b7a1f835310..8998523bb60 100644 --- a/base/applications/network/telnet/src/tnclass.cpp +++ b/base/applications/network/telnet/src/tnclass.cpp @@ -41,10 +41,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include -#include "tnclass.h" -#include "tnmisc.h" +#include "precomp.h" // Mingw32 needs these (Paul Brannan 9/4/98) #ifndef ICON_SMALL diff --git a/base/applications/network/telnet/src/tnclip.cpp b/base/applications/network/telnet/src/tnclip.cpp index 54f3eba2308..ec47838614e 100644 --- a/base/applications/network/telnet/src/tnclip.cpp +++ b/base/applications/network/telnet/src/tnclip.cpp @@ -28,8 +28,7 @@ // Written by Paul Brannan // Last modified 7/12/98 -#include -#include "tnclip.h" +#include "precomp.h" Tnclip::Tnclip(HWND W, TNetwork &RefNetwork): Network(RefNetwork) { Window = W; diff --git a/base/applications/network/telnet/src/tncon.cpp b/base/applications/network/telnet/src/tncon.cpp index 10e9d4d0aed..6681317f2ee 100644 --- a/base/applications/network/telnet/src/tncon.cpp +++ b/base/applications/network/telnet/src/tncon.cpp @@ -43,10 +43,8 @@ // Original code // /////////////////////////////////////////////////////////////////////////////// -#include "tncon.h" -#include "keytrans.h" -#include "ttelhndl.h" -#include "tconsole.h" + +#include "precomp.h" #define KEYEVENT InputRecord[i].Event.KeyEvent diff --git a/base/applications/network/telnet/src/tnconfig.cpp b/base/applications/network/telnet/src/tnconfig.cpp index 5bd8dfaef21..9a9ad5ce192 100644 --- a/base/applications/network/telnet/src/tnconfig.cpp +++ b/base/applications/network/telnet/src/tnconfig.cpp @@ -30,14 +30,7 @@ // This is a class designed for use with Brad Johnson's Console Telnet // see the file tnconfig.h for more information -#include -#include -#include -#include -#include -#include -#include -#include "tnconfig.h" +#include "precomp.h" // Turn off the "forcing value to bool 'true' or 'false'" warning #ifdef _MSC_VER diff --git a/base/applications/network/telnet/src/tnerror.cpp b/base/applications/network/telnet/src/tnerror.cpp index 74249cb55a0..1a77ed9bc2b 100644 --- a/base/applications/network/telnet/src/tnerror.cpp +++ b/base/applications/network/telnet/src/tnerror.cpp @@ -42,13 +42,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tnerror.h" -#include "ttelhndl.h" // Paul Brannan 5/25/98 -#include "tnconfig.h" // Paul Brannan 5/25/98 -#include -#include -#include -#include +#include "precomp.h" #ifndef LANG_USER_DEFAULT #define LANG_USER_DEFAULT 400 diff --git a/base/applications/network/telnet/src/tnetwork.cpp b/base/applications/network/telnet/src/tnetwork.cpp index 64eed9be358..8cab0d564bd 100644 --- a/base/applications/network/telnet/src/tnetwork.cpp +++ b/base/applications/network/telnet/src/tnetwork.cpp @@ -35,7 +35,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include "tnetwork.h" +#include "precomp.h" void TNetwork::SetSocket(SOCKET s) { socket = s; diff --git a/base/applications/network/telnet/src/tnmain.cpp b/base/applications/network/telnet/src/tnmain.cpp index 011686baa78..0fc983b2cd3 100644 --- a/base/applications/network/telnet/src/tnmain.cpp +++ b/base/applications/network/telnet/src/tnmain.cpp @@ -42,10 +42,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include -#include "tnmain.h" -#include "tnmisc.h" +#include "precomp.h" int telCommandLine (Telnet &MyConnection); diff --git a/base/applications/network/telnet/src/tnmisc.cpp b/base/applications/network/telnet/src/tnmisc.cpp index 25e319a81aa..0698b19fccd 100644 --- a/base/applications/network/telnet/src/tnmisc.cpp +++ b/base/applications/network/telnet/src/tnmisc.cpp @@ -1,7 +1,4 @@ -#include -#include - -#include "tnmisc.h" +#include "precomp.h" // from the PVAX (http://www.ccas.ru/~posp/popov/spawn.htm) // Create a process with pipes to stdin/out/err diff --git a/base/applications/network/telnet/src/tscript.cpp b/base/applications/network/telnet/src/tscript.cpp index 2045e43ce17..24774a77683 100644 --- a/base/applications/network/telnet/src/tscript.cpp +++ b/base/applications/network/telnet/src/tscript.cpp @@ -23,7 +23,7 @@ // /////////////////////////////////////////////////////////////////////////// -#include "tscript.h" +#include "precomp.h" // FIX ME!! This code not yet functional. diff --git a/base/applications/network/telnet/src/tscroll.cpp b/base/applications/network/telnet/src/tscroll.cpp index 6c8294ede4a..0b2a3e19d18 100644 --- a/base/applications/network/telnet/src/tscroll.cpp +++ b/base/applications/network/telnet/src/tscroll.cpp @@ -38,13 +38,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include "tscroll.h" -#include "tncon.h" -#include "tconsole.h" -#include "tnconfig.h" +#include "precomp.h" enum { HEX, diff --git a/base/applications/network/telnet/src/ttelhndl.cpp b/base/applications/network/telnet/src/ttelhndl.cpp index 0020f3558f3..9caabc1be83 100644 --- a/base/applications/network/telnet/src/ttelhndl.cpp +++ b/base/applications/network/telnet/src/ttelhndl.cpp @@ -38,11 +38,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include "ttelhndl.h" -#include "telnet.h" -#include "tnconfig.h" -#include "tparams.h" +#include "precomp.h" int naws_string(char *buf, int width, int height); diff --git a/base/applications/rapps/CMakeLists.txt b/base/applications/rapps/CMakeLists.txt index aeeb6815201..46099e4e548 100644 --- a/base/applications/rapps/CMakeLists.txt +++ b/base/applications/rapps/CMakeLists.txt @@ -26,6 +26,7 @@ include_directories( set_rc_compiler() add_executable(rapps ${SOURCE}) +add_pch(rapps rapps.h) set_module_type(rapps win32gui) target_link_libraries(rapps uuid) diff --git a/base/applications/rapps/lang/zh-CN.rc b/base/applications/rapps/lang/zh-CN.rc new file mode 100644 index 00000000000..cc9f36ebf0e --- /dev/null +++ b/base/applications/rapps/lang/zh-CN.rc @@ -0,0 +1,197 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDR_MAINMENU MENU +BEGIN + POPUP "文件(&F)" + BEGIN + MENUITEM "设置(&S)", ID_SETTINGS + MENUITEM SEPARATOR + MENUITEM "退出(&X)", ID_EXIT + END + POPUP "程序(&P)" + BEGIN + MENUITEM "安装(&I)", ID_INSTALL + MENUITEM "卸载(&U)",ID_UNINSTALL + MENUITEM "修改(&M)", ID_MODIFY + MENUITEM SEPARATOR + MENUITEM "从注册表删除(&E)", ID_REGREMOVE + MENUITEM SEPARATOR + MENUITEM "刷新(&R)", ID_REFRESH + END + POPUP "帮助" + BEGIN + MENUITEM "帮助内容", ID_HELP, GRAYED + MENUITEM "关于", ID_ABOUT + END +END + +IDR_LINKMENU MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM "在浏览器中打开链接(&O)", ID_OPEN_LINK + MENUITEM "复制链接到剪贴板(&C)", ID_COPY_LINK + END +END + +IDR_APPLICATIONMENU MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM "安装(&I)", ID_INSTALL + MENUITEM "卸载(&U)", ID_UNINSTALL + MENUITEM "修改(&M)", ID_MODIFY + MENUITEM SEPARATOR + MENUITEM "从注册表删除(&E)", ID_REGREMOVE + MENUITEM SEPARATOR + MENUITEM "刷新(&R)", ID_REFRESH + END +END + +IDD_SETTINGS_DIALOG DIALOGEX DISCARDABLE 0, 0, 250, 144 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "设置" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "普通", -1, 4, 2, 240, 61 + AUTOCHECKBOX "保存窗口位置(&S)", IDC_SAVE_WINDOW_POS, 15, 12, 219, 12 + AUTOCHECKBOX "启动时更新可获得的程序列表(&U)", IDC_UPDATE_AVLIST, 15, 29, 219, 12 + AUTOCHECKBOX "将程序的安装和卸载记录到日志(&L)", IDC_LOG_ENABLED, 15, 46, 219, 12 + + GROUPBOX "正在下载", -1, 4, 65, 240, 51 + LTEXT "下载文件夹:", -1, 16, 75, 100, 9 + EDITTEXT IDC_DOWNLOAD_DIR_EDIT, 15, 86, 166, 12, WS_CHILD | WS_VISIBLE | WS_GROUP + PUSHBUTTON "选择(&C)", IDC_CHOOSE, 187, 85, 50, 14 + AUTOCHECKBOX "在安装完程序后删除安装程序(&D)", IDC_DEL_AFTER_INSTALL, 16, 100, 218, 12 + + PUSHBUTTON "缺省", IDC_DEFAULT_SETTINGS, 8, 124, 60, 14 + PUSHBUTTON "确定", IDOK, 116, 124, 60, 14 + PUSHBUTTON "取消", IDCANCEL, 181, 124, 60, 14 +END + +IDD_INSTALL_DIALOG DIALOGEX DISCARDABLE 0, 0, 216, 97 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "安装程序" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "...", IDC_INSTALL_TEXT, 4, 5, 209, 35 + + AUTORADIOBUTTON "从存储设备安装 (CD 或 DVD)(&I)", IDC_CD_INSTALL, 10, 46, 197, 11, WS_GROUP + AUTORADIOBUTTON "下载并安装(&D)", IDC_DOWNLOAD_INSTALL, 10, 59, 197, 11, NOT WS_TABSTOP + + PUSHBUTTON "确定", IDOK, 86, 78, 60, 14 + PUSHBUTTON "取消", IDCANCEL, 150, 78, 60, 14 +END + +IDD_DOWNLOAD_DIALOG DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 +STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE +CAPTION "正在下载..." +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Progress1", IDC_DOWNLOAD_PROGRESS, "msctls_progress32", WS_BORDER | PBS_SMOOTH, 10, 10, 200, 12 + LTEXT "", IDC_DOWNLOAD_STATUS, 10, 30, 200, 10, SS_CENTER + PUSHBUTTON "取消", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP +END + +IDD_ABOUT_DIALOG DIALOGEX 22, 16, 190, 66 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +CAPTION "关于" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "ReactOS 程序管理器\版权所有 (C) 2009\n作者 Dmitry Chapyshev (dmitry@reactos.org)", IDC_STATIC, 48, 7, 130, 39 + PUSHBUTTON "关闭", IDOK, 133, 46, 50, 14 + ICON IDI_MAIN, IDC_STATIC, 10, 10, 7, 30 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_INSTALL "安装" + IDS_TOOLTIP_UNINSTALL "卸载" + IDS_TOOLTIP_MODIFY "修改" + IDS_TOOLTIP_SETTINGS "设置" + IDS_TOOLTIP_REFRESH "刷新" + IDS_TOOLTIP_EXIT "退出" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_NAME "名称" + IDS_APP_INST_VERSION "版本" + IDS_APP_DESCRIPTION "描述" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_INFO_VERSION "\版本:" + IDS_INFO_DESCRIPTION "\描述:" + IDS_INFO_PUBLISHER "\n发布者:" + IDS_INFO_HELPLINK "\n帮助链接:" + IDS_INFO_HELPPHONE "\n帮助电话:" + IDS_INFO_README "\n必读:" + IDS_INFO_REGOWNER "\n注册所有者:" + IDS_INFO_PRODUCTID "\n产品 ID:" + IDS_INFO_CONTACT "\n联系方式:" + IDS_INFO_UPDATEINFO "\n更新信息:" + IDS_INFO_INFOABOUT "\n关于信息:" + IDS_INFO_COMMENTS "\n注释:" + IDS_INFO_INSTLOCATION "\n安装位置:" + IDS_INFO_INSTALLSRC "\n安装源:" + IDS_INFO_UNINSTALLSTR "\n卸载字符串:" + IDS_INFO_MODIFYPATH "\n修改路径:" + IDS_INFO_INSTALLDATE "\n安装日期:" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_AINFO_VERSION "\n版本:" + IDS_AINFO_DESCRIPTION "\n描述:" + IDS_AINFO_SIZE "\n大小:" + IDS_AINFO_URLSITE "\n主页:" + IDS_AINFO_LICENCE "\n协议:" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CAT_AUDIO "音频" + IDS_CAT_DEVEL "开发" + IDS_CAT_DRIVERS "驱动程序" + IDS_CAT_EDU "教育与娱乐" + IDS_CAT_ENGINEER "工程" + IDS_CAT_FINANCE "经济" + IDS_CAT_GAMES "游戏与娱乐" + IDS_CAT_GRAPHICS "图形" + IDS_CAT_INTERNET "Internet 与网络" + IDS_CAT_LIBS "库" + IDS_CAT_OFFICE "办公" + IDS_CAT_OTHER "其他" + IDS_CAT_SCIENCE "科学" + IDS_CAT_TOOLS "工具" + IDS_CAT_VIDEO "视频" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPTITLE "ReactOS 程序管理器" + IDS_SEARCH_TEXT "搜索..." + IDS_INSTALL "安装" + IDS_UNINSTALL "卸载" + IDS_MODIFY "修改" + IDS_APPS_COUNT "程序个数:%d" + IDS_WELCOME_TITLE "欢迎来到 ReactOS 程序管理器!\n\n" + IDS_WELCOME_TEXT "从左栏选择一个类别,然后选择要安装或卸载的程序。\nReactOS 网站:" + IDS_WELCOME_URL "http://www.reactos.org" + IDS_INSTALLED "已安装" + IDS_AVAILABLEFORINST "可安装" + IDS_UPDATES "更新" + IDS_APPLICATIONS "应用程序" + IDS_CHOOSE_FOLDER_TEXT "请选择用来保存下载文件的文件夹:" + IDS_CHOOSE_FOLDER_ERROR "您选择的文件夹不存在。创建吗?" + IDS_USER_NOT_ADMIN "您必须以管理员权限启动 ""ReactOS 程序管理器""!" + IDS_APP_REG_REMOVE "您确定要从注册表删除该程序的数据吗?" + IDS_INFORMATION "信息" + IDS_UNABLE_TO_REMOVE "无法从注册表删除该程序的数据!" +END diff --git a/base/applications/rapps/loaddlg.c b/base/applications/rapps/loaddlg.c index 206eb39e5e5..ab4022391df 100644 --- a/base/applications/rapps/loaddlg.c +++ b/base/applications/rapps/loaddlg.c @@ -29,12 +29,6 @@ #define WIN32_NO_STATUS #include "rapps.h" -#include "resource.h" - -#include -#include -#include -#include static PAPPLICATION_INFO AppInfo; static HICON hIcon = NULL; diff --git a/base/applications/rapps/rapps.h b/base/applications/rapps/rapps.h index cba76db823a..261813af0fe 100644 --- a/base/applications/rapps/rapps.h +++ b/base/applications/rapps/rapps.h @@ -1,11 +1,10 @@ -#pragma once - #include #include #include #include #include #include +#include #include diff --git a/base/applications/rapps/rapps/bittorrent.txt b/base/applications/rapps/rapps/bittorrent.txt new file mode 100644 index 00000000000..d23ba34bcfa --- /dev/null +++ b/base/applications/rapps/rapps/bittorrent.txt @@ -0,0 +1,16 @@ +; UTF-8 + +[Section] +Name = BitTorrent +Version = 7.2.1 +Licence = Freeware for non-commercial uses +Description = The Original BitTorrent Client. +Size = 394K +Category = 5 +URLSite = http://www.bittorrent.com/ +URLDownload = http://download.bittorrent.com/dl/BitTorrent-7.2.1.exe +CDPath = none + +[Section.0407] +Licence = Freeware für nichtkommerzielle Nutzung +Description = Der Original BitTorrent Client. diff --git a/base/applications/rapps/rapps/fap.txt b/base/applications/rapps/rapps/fap.txt index 2ea6cf397dd..c08fea3eeb3 100644 --- a/base/applications/rapps/rapps/fap.txt +++ b/base/applications/rapps/rapps/fap.txt @@ -2,13 +2,13 @@ [Section] Name = Fox Audio Player -Version = 0.8.3 +Version = 0.8.8 Licence = GPL Description = Simple and lightweight audio player. Size = 1.85MB Category = 1 URLSite = http://foxaudioplayer.sourceforge.net/ -URLDownload = http://svn.reactos.org/packages/fap-0.8.3-win32-bin.exe +URLDownload = http://svn.reactos.org/packages/fap-0.8.8-win32-bin.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/firefox36.txt b/base/applications/rapps/rapps/firefox36.txt index af292db6042..c05f2df6c91 100644 --- a/base/applications/rapps/rapps/firefox36.txt +++ b/base/applications/rapps/rapps/firefox36.txt @@ -2,59 +2,59 @@ [Section] Name = Mozilla Firefox 3.6 -Version = 3.6.16 +Version = 3.6.19 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Web Browsers out there. Size = 8.2M Category = 5 URLSite = http://www.mozilla.com/en-US/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/en-US/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/en-US/Firefox%20Setup%203.6.19.exe CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Webbrowser. -Size = 8.1M +Size = 8.0M URLSite = http://www.mozilla-europe.org/de/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/de/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/de/Firefox%20Setup%203.6.19.exe [Section.040a] Description = El más popular y uno de los mejores navegadores web gratuitos que hay. -Size = 8.1M +Size = 8.0M URLSite = http://www.mozilla-europe.org/es/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/es-ES/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/es-ES/Firefox%20Setup%203.6.19.exe [Section.040c] Description = Le navigateur web gratuit le plus populaire et l'un des meilleurs. -Size = 8.1M +Size = 8.0M URLSite = http://www.mozilla-europe.org/fr/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/fr/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/fr/Firefox%20Setup%203.6.19.exe [Section.0414] Description = Mest populære og best ogsÃ¥ gratis nettleserene der ute. -Size = 8.1M +Size = 8.0M URLSite = http://www.mozilla-europe.org/no/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/nb-NO/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/nb-NO/Firefox%20Setup%203.6.19.exe [Section.0415] Description = Najpopularniejsza i jedna z najlepszych darmowych przeglądarek internetowych. Size = 8.9M URLSite = http://www.mozilla-europe.org/pl/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/pl/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/pl/Firefox%20Setup%203.6.19.exe [Section.0419] Description = Один из самых популярных и лучших бесплатных браузеров. -Size = 8.5M +Size = 8.4M URLSite = http://www.mozilla-europe.org/ru/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/ru/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/ru/Firefox%20Setup%203.6.19.exe [Section.041b] Description = Najpopulárnejší a jeden z najlepších slobodný webových prehliadačov. -Size = 8,5 MB +Size = 8,5MB URLSite = http://www.mozilla-europe.org/sk/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/sk/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/sk/Firefox%20Setup%203.6.19.exe [Section.0422] Description = Найпопулярніший та один з кращих безплатних веб-браузерів. -Size = 8.5M +Size = 8.4M URLSite = http://www.mozilla-europe.org/uk/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.16/win32/uk/Firefox%20Setup%203.6.16.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/3.6.19/win32/uk/Firefox%20Setup%203.6.19.exe diff --git a/base/applications/rapps/rapps/firefox4.txt b/base/applications/rapps/rapps/firefox5.txt similarity index 55% rename from base/applications/rapps/rapps/firefox4.txt rename to base/applications/rapps/rapps/firefox5.txt index 650153b0176..d023382d046 100644 --- a/base/applications/rapps/rapps/firefox4.txt +++ b/base/applications/rapps/rapps/firefox5.txt @@ -1,60 +1,60 @@ -; UTF-8 +; UTF-8 [Section] -Name = Mozilla Firefox 4 -Version = 4.0.1 +Name = Mozilla Firefox 5 +Version = 5.0.1 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Web Browsers out there. -Size = 11.9M +Size = 13.1M Category = 5 URLSite = http://www.mozilla.com/en-US/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/en-US/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/en-US/Firefox%20Setup%205.0.1.exe CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Webbrowser. -Size = 11.7M +Size = 12.9M URLSite = http://www.mozilla-europe.org/de/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/de/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/de/Firefox%20Setup%205.0.1.exe [Section.040a] Description = El más popular y uno de los mejores navegadores web gratuitos que hay. -Size = 11.9M +Size = 12.9M URLSite = http://www.mozilla-europe.org/es/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/es-ES/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/es-ES/Firefox%20Setup%205.0.1.exe [Section.040c] Description = Le navigateur web gratuit le plus populaire et l'un des meilleurs. -Size = 12.0M +Size = 13.2M URLSite = http://www.mozilla-europe.org/fr/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/fr/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/fr/Firefox%20Setup%205.0.1.exe [Section.0414] Description = Mest populære og best ogsÃ¥ gratis nettleserene der ute. -Size = 11.7M +Size = 12.9M URLSite = http://www.mozilla-europe.org/no/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/nb-NO/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/nb-NO/Firefox%20Setup%205.0.1.exe [Section.0415] Description = Najpopularniejsza i jedna z najlepszych darmowych przeglądarek internetowych. -Size = 12.6M +Size = 13.7M URLSite = http://www.mozilla-europe.org/pl/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/pl/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/pl/Firefox%20Setup%205.0.1.exe [Section.0419] Description = Один из самых популярных и лучших бесплатных браузеров. -Size = 12.2M +Size = 13.3M URLSite = http://www.mozilla-europe.org/ru/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/ru/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/ru/Firefox%20Setup%205.0.1.exe [Section.041b] Description = Najpopulárnejší a jeden z najlepších slobodný webových prehliadačov. -Size = 12.4 MB +Size = 13.6MB URLSite = http://www.mozilla-europe.org/sk/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/sk/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/sk/Firefox%20Setup%205.0.1.exe [Section.0422] Description = Найпопулярніший та один з кращих безплатних веб-браузерів. -Size = 12.1M +Size = 13.3M URLSite = http://www.mozilla-europe.org/uk/ -URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/4.0.1/win32/uk/Firefox%20Setup%204.0.1.exe +URLDownload = http://mozilla.cdn.leaseweb.com/firefox/releases/5.0.1/win32/uk/Firefox%20Setup%205.0.1.exe diff --git a/base/applications/rapps/rapps/irfanview.txt b/base/applications/rapps/rapps/irfanview.txt index 044d478cef0..c12850d54e6 100644 --- a/base/applications/rapps/rapps/irfanview.txt +++ b/base/applications/rapps/rapps/irfanview.txt @@ -2,13 +2,13 @@ [Section] Name = IrfanView -Version = 4.28 +Version = 4.30 Licence = Freeware (for personal use) Description = Viewer for all kinds of graphics/audio files/video files. -Size = 1.3MB +Size = 1.4MB Category = 3 URLSite = http://www.irfanview.com/ -URLDownload = http://irfanview.tuwien.ac.at/iview428_setup.exe +URLDownload = http://irfanview.tuwien.ac.at/iview430_setup.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/irfanviewplugins.txt b/base/applications/rapps/rapps/irfanviewplugins.txt index 7a116f1d9ef..7b9d12bdbb6 100644 --- a/base/applications/rapps/rapps/irfanviewplugins.txt +++ b/base/applications/rapps/rapps/irfanviewplugins.txt @@ -2,13 +2,13 @@ [Section] Name = IrfanView Plugins -Version = 4.28 +Version = 4.30 Licence = Freeware (for personal use) Description = Additional Plugins for supporting more file types. -Size = 7.8MB +Size = 7.7MB Category = 3 URLSite = http://www.irfanview.com/ -URLDownload = http://irfanview.tuwien.ac.at/plugins/irfanview_plugins_428_setup.exe +URLDownload = http://irfanview.tuwien.ac.at/plugins/irfanview_plugins_430_setup.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/libreoffice.txt b/base/applications/rapps/rapps/libreoffice.txt index d609e3f80b4..18919049568 100644 --- a/base/applications/rapps/rapps/libreoffice.txt +++ b/base/applications/rapps/rapps/libreoffice.txt @@ -2,13 +2,13 @@ [Section] Name = LibreOffice -Version = 3.3.2 +Version = 3.3.3 Licence = LGPL Description = Former called OpenOffice. Open Source Office Suite. -Size = 214.0MB +Size = 217.0MB Category = 6 URLSite = http://www.documentfoundation.org/ -URLDownload = http://download.documentfoundation.org/libreoffice/stable/3.3.2/win/x86/LibO_3.3.2_Win_x86_install_multi.exe +URLDownload = http://download.documentfoundation.org/libreoffice/stable/3.3.3/win/x86/LibO_3.3.3_Win_x86_install_multi.exe CDPath = none [Section.0407] @@ -25,3 +25,5 @@ Description = Otwarty pakiet biurowy. [Section.0422] Description = Відкритий офісний пакет. +Size = 249.0M +URLDownload = http://download.documentfoundation.org/libreoffice/stable/3.3.3/win/x86/LibO_3.3.3_Win_x86_install_all_lang.exe diff --git a/base/applications/rapps/rapps/mirandaim.txt b/base/applications/rapps/rapps/mirandaim.txt index 9e1198eb888..f771ebd7faa 100644 --- a/base/applications/rapps/rapps/mirandaim.txt +++ b/base/applications/rapps/rapps/mirandaim.txt @@ -2,13 +2,13 @@ [Section] Name = Miranda IM -Version = 0.9.18 +Version = 0.9.25 Licence = GPL Description = Open source multiprotocol instant messaging application - May not work completely. -Size = 3.0MB +Size = 3.1MB Category = 5 URLSite = http://www.miranda-im.org/ -URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.18-unicode.exe +URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.25-unicode.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/seamonkey.txt b/base/applications/rapps/rapps/seamonkey.txt index 48579604d39..9d167c44b27 100644 --- a/base/applications/rapps/rapps/seamonkey.txt +++ b/base/applications/rapps/rapps/seamonkey.txt @@ -2,36 +2,41 @@ [Section] Name = Mozilla SeaMonkey -Version = 2.0.13 +Version = 2.2 Licence = MPL/GPL/LGPL Description = Mozilla Suite is alive. This is the one and only Browser, Mail, Chat, and Composer bundle you will ever need. -Size = 10.2MB +Size = 16.0MB Category = 5 URLSite = http://www.seamonkey-project.org/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.13/win32/en-US/SeaMonkey%20Setup%202.0.13.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/en-US/SeaMonkey%20Setup%202.2.exe CDPath = none [Section.0407] Description = Mozilla Suite lebt. Dies ist das einzige Browser-, Mail-, Chat- and Composerwerkzeug-Bundle welches Sie benötigen. -Size = 10.1MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.13/win32/de/SeaMonkey%20Setup%202.0.13.exe +Size = 16.0MB +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/de/SeaMonkey%20Setup%202.2.exe [Section.040a] Description = La suite de Mozilla está viva. Es el primero y único navegador web, gestor de correo, lector de noticias, Chat y editor HTML que necesitarás. -Size = 10.1MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.13/win32/es-ES/SeaMonkey%20Setup%202.0.13.exe +Size = 15.9MB +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/es-ES/SeaMonkey%20Setup%202.2.exe [Section.040c] Description = La suite Mozilla est en vie. Ceci est le seul et l'unique package navigateur, client mail, client chat et composer dont vous aurez besoin. -Size = 10.1MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.13/win32/fr/SeaMonkey%20Setup%202.0.13.exe +Size = 16.3MB +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/fr/SeaMonkey%20Setup%202.2.exe [Section.0415] Description = Pakiet Mozilla żyje. W zestawie: przeglądarka, klient poczty, IRC oraz Edytor HTML - wszystko, czego potrzebujesz. -Size = 11.0MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.13/win32/pl/SeaMonkey%20Setup%202.0.13.exe +Size = 16.8MB +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/pl/SeaMonkey%20Setup%202.2.exe [Section.0419] Description = Продолжение Mozilla Suite. Включает браузер, почтовый клиент, IRC-клиент и HTML-редактор. -Size = 10.5MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.13/win32/ru/SeaMonkey%20Setup%202.0.13.exe +Size = 16.4MB +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/ru/SeaMonkey%20Setup%202.2.exe + +[Section.0422] +Description = Продовження Mozilla Suite. Включає в себе браузер, поштовий клієнт, IRC-клієнт та HTML-редактор. +Size = 16.4MB +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.2/win32/ru/SeaMonkey%20Setup%202.2.exe diff --git a/base/applications/rapps/rapps/superfinder.txt b/base/applications/rapps/rapps/superfinder.txt index 04d6b0f1ead..0abc6654944 100644 --- a/base/applications/rapps/rapps/superfinder.txt +++ b/base/applications/rapps/rapps/superfinder.txt @@ -2,13 +2,13 @@ [Section] Name = Super Finder XT -Version = 1.6.2.1 +Version = 1.6.3.2 Licence = Freeware Description = A fast and feature rich search Application. -Size = 4.5MB +Size = 4.9MB Category = 12 URLSite = http://fsl.sytes.net/ssearchxt.html -URLDownload = http://fsl.sytes.net/releases/setup_SuperFinderXT.exe +URLDownload = http://www.webalice.it/guido.vinaio/releases/setup_SuperFinderXT.exe CDPath = none [Section.0407] @@ -22,3 +22,6 @@ Description = Une application de recherche rapide et riche en fonctionnalités. [Section.0415] Description = Szybka i bogata w opcje aplikacja szukająca. + +[Section.0422] +Description = Швидка та потужна програма пошуку. diff --git a/base/applications/rapps/rapps/thunderbird.txt b/base/applications/rapps/rapps/thunderbird.txt index e91eb6c7182..29c02381281 100644 --- a/base/applications/rapps/rapps/thunderbird.txt +++ b/base/applications/rapps/rapps/thunderbird.txt @@ -2,47 +2,47 @@ [Section] Name = Mozilla Thunderbird -Version = 3.1.9 +Version = 3.1.11 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Mail Clients out there. Size = 9.0M Category = 5 URLSite = http://www.mozilla-europe.org/en/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/en-US/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/en-US/Thunderbird%20Setup%203.1.11.exe CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Mail-Clients. -Size = 8.8M +Size = 8.9M URLSite = http://www.mozilla-europe.org/de/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/de/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/de/Thunderbird%20Setup%203.1.11.exe [Section.040a] Description = El más popular y uno de los mejores clientes mail que hay. -Size = 8.8M +Size = 8.9M URLSite = http://www.mozilla-europe.org/es/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/es-ES/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/es-ES/Thunderbird%20Setup%203.1.11.exe [Section.040c] Description = Le plus populaire et l'un des meilleurs clients mail gratuits disponible. -Size = 8.8M +Size = 8.9M URLSite = http://www.mozilla-europe.org/fr/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/fr/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/fr/Thunderbird%20Setup%203.1.11.exe [Section.0415] Description = Najpopularniejszy i jeden z najlepszych darmowych klientów poczty. Size = 9.7M URLSite = http://www.mozilla-europe.org/pl/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/pl/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/pl/Thunderbird%20Setup%203.1.11.exe [Section.0419] Description = Один из самых популярных и лучших бесплатных почтовых клиентов. -Size = 9.2M +Size = 9.3M URLSite = http://www.mozilla-europe.org/ru/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/ru/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/ru/Thunderbird%20Setup%203.1.11.exe [Section.0422] Description = Найпопулярніший та один з кращих поштових клієнтів. -Size = 9.2M +Size = 9.3M URLSite = http://www.mozillamessaging.com/uk/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.9/win32/uk/Thunderbird%20Setup%203.1.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.11/win32/uk/Thunderbird%20Setup%203.1.11.exe diff --git a/base/applications/rapps/rapps/thunderbird5.txt b/base/applications/rapps/rapps/thunderbird5.txt new file mode 100644 index 00000000000..87c5a45c1ae --- /dev/null +++ b/base/applications/rapps/rapps/thunderbird5.txt @@ -0,0 +1,48 @@ +; UTF-8 + +[Section] +Name = Mozilla Thunderbird 5 +Version = 5.0 +Licence = MPL/GPL/LGPL +Description = The most popular and one of the best free Mail Clients out there. +Size = 13.4M +Category = 5 +URLSite = http://www.mozilla-europe.org/en/products/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/en-US/Thunderbird%20Setup%205.0.exe +CDPath = none + +[Section.0407] +Description = Der populärste und einer der besten freien Mail-Clients. +Size = 13.3M +URLSite = http://www.mozilla-europe.org/de/products/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/de/Thunderbird%20Setup%205.0.exe + +[Section.040a] +Description = El más popular y uno de los mejores clientes mail que hay. +Size = 13.2M +URLSite = http://www.mozilla-europe.org/es/products/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/es-ES/Thunderbird%20Setup%205.0.exe + +[Section.040c] +Description = Le plus populaire et l'un des meilleurs clients mail gratuits disponible. +Size = 13.5M +URLSite = http://www.mozilla-europe.org/fr/products/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/fr/Thunderbird%20Setup%205.0.exe + +[Section.0415] +Description = Najpopularniejszy i jeden z najlepszych darmowych klientów poczty. +Size = 14.1M +URLSite = http://www.mozilla-europe.org/pl/products/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/pl/Thunderbird%20Setup%205.0.exe + +[Section.0419] +Description = Один из самых популярных и лучших бесплатных почтовых клиентов. +Size = 13.7M +URLSite = http://www.mozilla-europe.org/ru/products/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/ru/Thunderbird%20Setup%205.0.exe + +[Section.0422] +Description = Найпопулярніший та один з кращих поштових клієнтів. +Size = 13.7M +URLSite = http://www.mozillamessaging.com/uk/thunderbird/ +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/5.0/win32/uk/Thunderbird%20Setup%205.0.exe diff --git a/base/applications/rapps/rapps/vlc.txt b/base/applications/rapps/rapps/vlc.txt index a5cf92e77c4..8fec78f7367 100644 --- a/base/applications/rapps/rapps/vlc.txt +++ b/base/applications/rapps/rapps/vlc.txt @@ -2,13 +2,13 @@ [Section] Name = VLC media player -Version = 1.1.8 +Version = 1.1.11 Licence = GPL Description = A media player. -Size = 19.6MB +Size = 20.1MB Category = 1 URLSite = http://www.videolan.org/vlc/ -URLDownload = http://kent.dl.sourceforge.net/project/vlc/1.1.8/win32/vlc-1.1.8-win32.exe +URLDownload = http://kent.dl.sourceforge.net/project/vlc/1.1.11/win32/vlc-1.1.11-win32.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rsrc.rc b/base/applications/rapps/rsrc.rc index cd56fb7ae25..350e60534c0 100644 --- a/base/applications/rapps/rsrc.rc +++ b/base/applications/rapps/rsrc.rc @@ -13,3 +13,4 @@ #include "lang/sk-SK.rc" #include "lang/sv-SE.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/screensavers/3dtext/3dtext.c b/base/applications/screensavers/3dtext/3dtext.c index 7b8d11f34cb..924699d1e81 100644 --- a/base/applications/screensavers/3dtext/3dtext.c +++ b/base/applications/screensavers/3dtext/3dtext.c @@ -18,14 +18,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include -#include -#include -#include -#include -#include - -#include "resource.h" #include "3dtext.h" static HGLRC hRC; // Permanent Rendering Context diff --git a/base/applications/screensavers/3dtext/3dtext.h b/base/applications/screensavers/3dtext/3dtext.h index 10cd1aaac95..d3e4b5f048e 100644 --- a/base/applications/screensavers/3dtext/3dtext.h +++ b/base/applications/screensavers/3dtext/3dtext.h @@ -20,6 +20,15 @@ ////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +#include "resource.h" + extern TCHAR m_Text[MAX_PATH]; VOID LoadSettings(VOID); diff --git a/base/applications/screensavers/3dtext/CMakeLists.txt b/base/applications/screensavers/3dtext/CMakeLists.txt index 083b0b0304d..cb4b77ca79e 100644 --- a/base/applications/screensavers/3dtext/CMakeLists.txt +++ b/base/applications/screensavers/3dtext/CMakeLists.txt @@ -8,8 +8,8 @@ add_executable(3dtext rsrc.rc) set_module_type(3dtext win32gui) +add_pch(3dtext 3dtext.h) set_target_properties(3dtext PROPERTIES SUFFIX ".scr") - target_link_libraries(3dtext scrnsave) add_importlibs(3dtext user32 gdi32 opengl32 glu32 advapi32 msvcrt kernel32) diff --git a/base/applications/screensavers/3dtext/lang/zh-CN.rc b/base/applications/screensavers/3dtext/lang/zh-CN.rc new file mode 100644 index 00000000000..533ec73f1a3 --- /dev/null +++ b/base/applications/screensavers/3dtext/lang/zh-CN.rc @@ -0,0 +1,21 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +DLG_SCRNSAVECONFIGURE DIALOGEX 0, 0, 273, 178 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "3D 文字屏幕保护程序设置" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "确定",IDOK,216,7,50,14 + PUSHBUTTON "取消",IDCANCEL,216,24,50,14 + EDITTEXT IDC_MESSAGE_TEXT,18,28,122,14,ES_AUTOHSCROLL + LTEXT "自定义文字",IDC_STATIC,18,17,65,8 +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_DESCRIPTION "3D 文字屏幕保护程序" +END diff --git a/base/applications/screensavers/3dtext/rsrc.rc b/base/applications/screensavers/3dtext/rsrc.rc index ba63942beb1..14b043bd6ae 100644 --- a/base/applications/screensavers/3dtext/rsrc.rc +++ b/base/applications/screensavers/3dtext/rsrc.rc @@ -30,3 +30,4 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/screensavers/3dtext/settings.c b/base/applications/screensavers/3dtext/settings.c index d21f56aaa06..5257a70da82 100644 --- a/base/applications/screensavers/3dtext/settings.c +++ b/base/applications/screensavers/3dtext/settings.c @@ -20,8 +20,6 @@ ////////////////////////////////////////////////////////////////// -#include -#include #include "3dtext.h" TCHAR m_Text[MAX_PATH]; diff --git a/base/applications/screensavers/logon/lang/zh-CN.rc b/base/applications/screensavers/logon/lang/zh-CN.rc new file mode 100644 index 00000000000..6fee2178edb --- /dev/null +++ b/base/applications/screensavers/logon/lang/zh-CN.rc @@ -0,0 +1,11 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + IDS_DESCRIPTION "登录屏幕保护程序" + IDS_TEXT "没有需要设置的选项。" +END diff --git a/base/applications/screensavers/logon/logon.rc b/base/applications/screensavers/logon/logon.rc index da126bd96cf..f04007a38f4 100644 --- a/base/applications/screensavers/logon/logon.rc +++ b/base/applications/screensavers/logon/logon.rc @@ -34,3 +34,4 @@ IDB_SERVER BITMAP DISCARDABLE "res/1.bmp" #include "lang/ro-RO.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/shutdown/lang/zh-CN.rc b/base/applications/shutdown/lang/zh-CN.rc new file mode 100644 index 00000000000..4d99b281f68 --- /dev/null +++ b/base/applications/shutdown/lang/zh-CN.rc @@ -0,0 +1,18 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE DISCARDABLE +BEGIN + +IDS_USAGE, "用法: shutdown [-?] [-l | -s | -r] [-f]\n\n\ + 没有参数或 -?\t显示这个消息\n\ + -l\t\t\t注销\n\ + -s\t\t\t关闭计算机\n\ + -r\t\t\t重新启动计算机\n\ + -f\t\t\t毫无警告地强行关闭正在运行的程序\n\ + \t\t\t如果您没有指定其他任何参数,这个选项\n\ + \t\t\t也会引起注销" +END diff --git a/base/applications/shutdown/rsrc.rc b/base/applications/shutdown/rsrc.rc index 0146711e08d..89144ec01a5 100644 --- a/base/applications/shutdown/rsrc.rc +++ b/base/applications/shutdown/rsrc.rc @@ -21,3 +21,4 @@ #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/sndrec32/lang/zh-CN.rc b/base/applications/sndrec32/lang/zh-CN.rc new file mode 100644 index 00000000000..e56f8c2f69d --- /dev/null +++ b/base/applications/sndrec32/lang/zh-CN.rc @@ -0,0 +1,59 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDC_REACTOS_SNDREC32 ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + +IDD_ABOUTBOX DIALOGEX 0, 0, 196, 75 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "关于 ReactOS 录音机" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON 128,IDC_REACTOS_SNDREC32,19,14,21,20 + LTEXT "ReactOS 录音机,版本 1.0",IDC_STATIC,56,16,114,8,SS_NOPREFIX + LTEXT "版权所有 (C) 2009",IDC_STATIC,55,25,114,8 + DEFPUSHBUTTON "确定",IDOK,139,54,50,14,WS_GROUP +END + +IDR_MENU1 MENU +BEGIN + POPUP "文件" + BEGIN + MENUITEM "新建", ID_NEW + MENUITEM "打开...", ID_FILE_OPEN + MENUITEM "保存", ID_FILE_SAVE, GRAYED + MENUITEM "另存为...", ID_FILE_SAVEAS, GRAYED + MENUITEM SEPARATOR + MENUITEM "退出", ID_EXIT + END + MENUITEM "todo1", 0 + MENUITEM "todo2", 0 + POPUP "帮助" + BEGIN + MENUITEM "关于...", ID__ABOUT + END +END + +STRINGTABLE +BEGIN + IDS_APP_TITLE "录音机" + IDC_REACTOS_SNDREC32 "REACTOS_SNDREC32" +END + +STRINGTABLE +BEGIN + IDS_STRPOS "位置:%.2f 秒" + IDS_STRDUR "长度:%.2f 秒" + IDS_STRBUF "缓冲区:%.2f KiB" + IDS_STRFMT "%.1f kHz %u 位" + IDS_STRMONO "单声道" + IDS_STRSTEREO "立体声" + IDS_STRCHAN "%s" +END diff --git a/base/applications/sndrec32/rsrc.rc b/base/applications/sndrec32/rsrc.rc index 8f0707e484c..d0dcb073614 100644 --- a/base/applications/sndrec32/rsrc.rc +++ b/base/applications/sndrec32/rsrc.rc @@ -30,3 +30,4 @@ IDB_BITMAP2_STOP_DIS BITMAP "resources/but_stop_dis.bmp" #pragma code_page(65001) #include "lang/pl-PL.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/applications/sndvol32/lang/zh-CN.rc b/base/applications/sndvol32/lang/zh-CN.rc new file mode 100644 index 00000000000..17e13cce06a --- /dev/null +++ b/base/applications/sndvol32/lang/zh-CN.rc @@ -0,0 +1,61 @@ +/* + * Translated by Song Fuchang (0xfc) + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +IDM_MAINMENU MENU DISCARDABLE +BEGIN + POPUP "选项(&P)" + BEGIN + MENUITEM "属性(&R)", IDC_PROPERTIES + MENUITEM "高级控制(&A)", IDC_ADVANCED_CONTROLS + MENUITEM SEPARATOR + MENUITEM "退出(&X)", IDC_EXIT + END + POPUP "帮助(&H)" + BEGIN + MENUITEM "帮助主题(&T)", IDC_HELP_TOPICS + MENUITEM SEPARATOR + MENUITEM "关于音量控制(&A)", IDC_ABOUT + END +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_SNDVOL32 "音量控制" + IDS_NOMIXERDEVICES "没有可用的混音器设备!这个程序即将退出。" +END + +IDD_PREFERENCES DIALOGEX 0, 0, 224, 250 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "属性" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "混音设备(&M):", -1, 7,8,48,9 + COMBOBOX IDC_MIXERDEVICE, 55,8,162,80, CBS_DROPDOWNLIST | WS_TABSTOP + GROUPBOX "为...调节音量:", -1, 7,25,211,77 + PUSHBUTTON "回放(&P)", IDC_PLAYBACK, 13,43,47,8, BS_AUTORADIOBUTTON + PUSHBUTTON "录音(&R)", IDC_RECORDING, 13,61,47,8, BS_AUTORADIOBUTTON + PUSHBUTTON "其他(&O):", IDC_OTHER, 13,80,42,8, BS_AUTORADIOBUTTON | WS_DISABLED + COMBOBOX IDC_LINE, 55,80,155,50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED + LTEXT "显示以下的音量控制:", IDC_LABELCONTROLS, 7, 109, 162, 8 + CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96 + + PUSHBUTTON "确定", IDOK, 114,226,50,14 + PUSHBUTTON "取消", IDCANCEL, 168,226,50,14 +END + +IDD_VOLUME_CTRL DIALOG 0, 0, 90, 150 +STYLE WS_POPUP | WS_BORDER +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "主要", IDC_LINE_NAME, 4, 7, 100, 15 + CONTROL "", -1, "static", SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE, 4, 30, 82, 1 + LTEXT "平衡", -1, 4, 35, 80, 42 + LTEXT "音量", -1, 4, 100, 77, 108 + CONTROL "", IDC_LINE_SLIDER_HORZ, "msctls_trackbar32", TBS_HORZ | TBS_AUTOTICKS | TBS_BOTH | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 25, 55, 85, 30 + CONTROL "", IDC_LINE_SLIDER_VERT, "msctls_trackbar32", TBS_VERT | TBS_AUTOTICKS | TBS_BOTH | TBS_DOWNISLEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 32, 115, 30, 70 + CHECKBOX "静音(&M)", IDC_LINE_SWITCH, 4, 190, 90, 12, BS_AUTOCHECKBOX + CONTROL "", IDC_LINE_SEP, "static", SS_ETCHEDVERT | WS_CHILD | WS_VISIBLE, 130, 7, 1, 200 +END diff --git a/base/applications/sndvol32/rsrc.rc b/base/applications/sndvol32/rsrc.rc index 8daa68c06a3..587b731ee0c 100644 --- a/base/applications/sndvol32/rsrc.rc +++ b/base/applications/sndvol32/rsrc.rc @@ -30,3 +30,4 @@ IDI_MAINAPP ICON DISCARDABLE resources/sndvol32.ico #include "lang/pl-PL.rc" #include "lang/ru-RU.rc" #include "lang/uk-UA.rc" +#include "lang/zh-CN.rc" diff --git a/base/services/audiosrv/CMakeLists.txt b/base/services/audiosrv/CMakeLists.txt index bd96bf7f3a6..57935335548 100644 --- a/base/services/audiosrv/CMakeLists.txt +++ b/base/services/audiosrv/CMakeLists.txt @@ -11,5 +11,6 @@ add_executable(audiosrv audiosrv.rc) set_module_type(audiosrv win32cui) +add_pch(audiosrv audiosrv.h) add_importlibs(audiosrv advapi32 user32 setupapi msvcrt kernel32) add_cd_file(TARGET audiosrv DESTINATION reactos/system32 FOR all) diff --git a/base/services/audiosrv/audiosrv.h b/base/services/audiosrv/audiosrv.h index 1fce5ce0841..61edb2e2627 100644 --- a/base/services/audiosrv/audiosrv.h +++ b/base/services/audiosrv/audiosrv.h @@ -6,6 +6,15 @@ * COPYRIGHT: Copyright 2007 Andrew Greenwood */ +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/base/services/audiosrv/debug.c b/base/services/audiosrv/debug.c index 9352fc923c2..bdb34a190fc 100644 --- a/base/services/audiosrv/debug.c +++ b/base/services/audiosrv/debug.c @@ -1,8 +1,6 @@ /* Service debugging (simply logs to a file) */ -#include -#include -#include +#include "audiosrv.h" void logmsg(char* string, ...) { diff --git a/base/services/audiosrv/main.c b/base/services/audiosrv/main.c index c987433cdb5..13c4a640312 100644 --- a/base/services/audiosrv/main.c +++ b/base/services/audiosrv/main.c @@ -6,9 +6,6 @@ * COPYRIGHT: Copyright 2007 Andrew Greenwood */ -#include - -#include #include "audiosrv.h" SERVICE_STATUS_HANDLE service_status_handle; diff --git a/base/services/audiosrv/pnp.c b/base/services/audiosrv/pnp.c index af1c4fce219..e85da65117e 100644 --- a/base/services/audiosrv/pnp.c +++ b/base/services/audiosrv/pnp.c @@ -6,15 +6,6 @@ * COPYRIGHT: Copyright 2007 Andrew Greenwood */ -#include -#include -#include -#include - -#include -#include - -#include #include "audiosrv.h" static HDEVNOTIFY device_notification_handle = NULL; diff --git a/base/services/audiosrv/pnp_list_lock.c b/base/services/audiosrv/pnp_list_lock.c index 07c6f6e308f..1ac7e6545e2 100644 --- a/base/services/audiosrv/pnp_list_lock.c +++ b/base/services/audiosrv/pnp_list_lock.c @@ -6,9 +6,7 @@ * COPYRIGHT: Copyright 2007 Andrew Greenwood */ -#include -#include -#include +#include "audiosrv.h" static HANDLE audio_device_list_lock = NULL; diff --git a/base/services/audiosrv/pnp_list_manager.c b/base/services/audiosrv/pnp_list_manager.c index cfafed070d9..457e8a442a3 100644 --- a/base/services/audiosrv/pnp_list_manager.c +++ b/base/services/audiosrv/pnp_list_manager.c @@ -6,9 +6,6 @@ * COPYRIGHT: Copyright 2007 Andrew Greenwood */ -#include -#include -#include #include "audiosrv.h" diff --git a/base/services/audiosrv/services.c b/base/services/audiosrv/services.c index 34dd2e285b9..dee6431629a 100644 --- a/base/services/audiosrv/services.c +++ b/base/services/audiosrv/services.c @@ -6,15 +6,6 @@ * COPYRIGHT: Copyright 2009 Johannes Anderwald */ -#include -#include -#include -#include - -#include -#include - -#include #include "audiosrv.h" BOOL diff --git a/base/services/eventlog/eventlog.c b/base/services/eventlog/eventlog.c index d0ee12f36ea..c988e1257b0 100644 --- a/base/services/eventlog/eventlog.c +++ b/base/services/eventlog/eventlog.c @@ -463,7 +463,7 @@ VOID SystemTimeToEventTime(SYSTEMTIME * pSystemTime, DWORD * pEventTime) SystemTimeToFileTime(pSystemTime, &Time.ft); SystemTimeToFileTime(&st1970, &u1970.ft); - *pEventTime = (Time.ll - u1970.ll) / 10000000; + *pEventTime = (DWORD)((Time.ll - u1970.ll) / 10000000ull); } VOID PRINT_HEADER(PEVENTLOGHEADER header) diff --git a/base/services/eventlog/file.c b/base/services/eventlog/file.c index 116d0d09102..8bd9ec0a159 100644 --- a/base/services/eventlog/file.c +++ b/base/services/eventlog/file.c @@ -896,17 +896,17 @@ DWORD LogfGetCurrentRecord(PLOGFILE LogFile) BOOL LogfDeleteOffsetInformation(PLOGFILE LogFile, ULONG ulNumber) { - int i; + DWORD i; if (ulNumber != LogFile->OffsetInfo[0].EventNumber) { return FALSE; } - for (i=0;iOffsetInfoNext-1; i++) + for (i = 0; i < LogFile->OffsetInfoNext - 1; i++) { - LogFile->OffsetInfo[i].EventNumber = LogFile->OffsetInfo[i+1].EventNumber; - LogFile->OffsetInfo[i].EventOffset = LogFile->OffsetInfo[i+1].EventOffset; + LogFile->OffsetInfo[i].EventNumber = LogFile->OffsetInfo[i + 1].EventNumber; + LogFile->OffsetInfo[i].EventOffset = LogFile->OffsetInfo[i + 1].EventOffset; } LogFile->OffsetInfoNext--; return TRUE; @@ -1102,4 +1102,4 @@ LogfReportEvent(WORD wType, } LogfFreeRecord(logBuffer); -} \ No newline at end of file +} diff --git a/base/services/telnetd/telnetd.rc b/base/services/telnetd/telnetd.rc index 53760e9b74b..2e0c42aac53 100644 --- a/base/services/telnetd/telnetd.rc +++ b/base/services/telnetd/telnetd.rc @@ -1,6 +1,6 @@ /* $Id$ */ -#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Simple Telnet Deamon\0" +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Simple Telnet Service\0" #define REACTOS_STR_INTERNAL_NAME "telnetd\0" #define REACTOS_STR_ORIGINAL_FILENAME "telnetd.exe\0" #define REACTOS_STR_ORIGINAL_COPYRIGHT "fred.van.lieshout 'at' zonnet.nl\0" diff --git a/base/services/wlansvc/wlansvc.c b/base/services/wlansvc/wlansvc.c index 5f0e1e6d95e..721dd0f9706 100644 --- a/base/services/wlansvc/wlansvc.c +++ b/base/services/wlansvc/wlansvc.c @@ -75,6 +75,7 @@ ServiceControlHandler(DWORD dwControl, case SERVICE_CONTROL_STOP: UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOP_PENDING, 1); RpcMgmtStopServerListening(NULL); + UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOPPED, 0); break; case SERVICE_CONTROL_INTERROGATE: return NO_ERROR; diff --git a/base/setup/usetup/bootsup.c b/base/setup/usetup/bootsup.c index 3f6c8a77b9b..64f10bc86f5 100644 --- a/base/setup/usetup/bootsup.c +++ b/base/setup/usetup/bootsup.c @@ -1,21 +1,3 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS text-mode setup @@ -34,66 +16,66 @@ #include typedef struct _FAT_BOOTSECTOR { - UCHAR JumpBoot[3]; // Jump instruction to boot code - CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes - USHORT BytesPerSector; // Bytes per sector - UCHAR SectorsPerCluster; // Number of sectors in a cluster - USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) - UCHAR NumberOfFats; // Number of FAT tables - USHORT RootDirEntries; // Number of root directory entries (fat12/16) - USHORT TotalSectors; // Number of total sectors on the drive, 16-bit - UCHAR MediaDescriptor; // Media descriptor byte - USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) - USHORT SectorsPerTrack; // Number of sectors in a track - USHORT NumberOfHeads; // Number of heads on the disk - ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) - ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume - UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) - UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. - UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. - ULONG VolumeSerialNumber; // Volume serial number - CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory - CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " - - UCHAR BootCodeAndData[448]; // The remainder of the boot sector - - USHORT BootSectorMagic; // 0xAA55 + UCHAR JumpBoot[3]; // Jump instruction to boot code + CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) + UCHAR NumberOfFats; // Number of FAT tables + USHORT RootDirEntries; // Number of root directory entries (fat12/16) + USHORT TotalSectors; // Number of total sectors on the drive, 16-bit + UCHAR MediaDescriptor; // Media descriptor byte + USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) + ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. + UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. + ULONG VolumeSerialNumber; // Volume serial number + CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory + CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " + + UCHAR BootCodeAndData[448]; // The remainder of the boot sector + + USHORT BootSectorMagic; // 0xAA55 } FAT_BOOTSECTOR, *PFAT_BOOTSECTOR; typedef struct _FAT32_BOOTSECTOR { - UCHAR JumpBoot[3]; // Jump instruction to boot code - CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes - USHORT BytesPerSector; // Bytes per sector - UCHAR SectorsPerCluster; // Number of sectors in a cluster - USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) - UCHAR NumberOfFats; // Number of FAT tables - USHORT RootDirEntries; // Number of root directory entries (fat12/16) - USHORT TotalSectors; // Number of total sectors on the drive, 16-bit - UCHAR MediaDescriptor; // Media descriptor byte - USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) - USHORT SectorsPerTrack; // Number of sectors in a track - USHORT NumberOfHeads; // Number of heads on the disk - ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) - ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume - ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 - USHORT ExtendedFlags; // Extended flags (fat32) - USHORT FileSystemVersion; // File system version (fat32) - ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32) - USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. - USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. - UCHAR Reserved[12]; // Reserved for future expansion - UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) - UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. - UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. - ULONG VolumeSerialNumber; // Volume serial number - CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory - CHAR FileSystemType[8]; // Always set to the string "FAT32 " - - UCHAR BootCodeAndData[420]; // The remainder of the boot sector - - USHORT BootSectorMagic; // 0xAA55 + UCHAR JumpBoot[3]; // Jump instruction to boot code + CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) + UCHAR NumberOfFats; // Number of FAT tables + USHORT RootDirEntries; // Number of root directory entries (fat12/16) + USHORT TotalSectors; // Number of total sectors on the drive, 16-bit + UCHAR MediaDescriptor; // Media descriptor byte + USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) + ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume + ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 + USHORT ExtendedFlags; // Extended flags (fat32) + USHORT FileSystemVersion; // File system version (fat32) + ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32) + USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. + USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. + UCHAR Reserved[12]; // Reserved for future expansion + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. + UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. + ULONG VolumeSerialNumber; // Volume serial number + CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory + CHAR FileSystemType[8]; // Always set to the string "FAT32 " + + UCHAR BootCodeAndData[420]; // The remainder of the boot sector + + USHORT BootSectorMagic; // 0xAA55 } FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR; #include @@ -103,320 +85,318 @@ extern PPARTLIST PartitionList; /* FUNCTIONS ****************************************************************/ -static VOID +static +VOID CreateCommonFreeLoaderSections(PINICACHE IniCache) { - PINICACHESECTION IniSection; + PINICACHESECTION IniSection; - /* Create "FREELOADER" section */ - IniSection = IniCacheAppendSection(IniCache, - L"FREELOADER"); + /* Create "FREELOADER" section */ + IniSection = IniCacheAppendSection(IniCache, + L"FREELOADER"); #if DBG - if (IsUnattendedSetup) - { - /* DefaultOS=ReactOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"DefaultOS", - L"ReactOS_KdSerial"); - } - else + if (IsUnattendedSetup) + { + /* DefaultOS=ReactOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"DefaultOS", + L"ReactOS_KdSerial"); + } + else #endif - { - /* DefaultOS=ReactOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"DefaultOS", - L"ReactOS"); - } + { + /* DefaultOS=ReactOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"DefaultOS", + L"ReactOS"); + } #if DBG - if (IsUnattendedSetup) + if (IsUnattendedSetup) #endif - { - /* Timeout=0 for unattended or non debug*/ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TimeOut", - L"0"); - } + { + /* Timeout=0 for unattended or non debug*/ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TimeOut", + L"0"); + } #if DBG - else - { - /* Timeout=0 or 10 */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TimeOut", - L"10"); - } + else + { + /* Timeout=0 or 10 */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TimeOut", + L"10"); + } #endif - /* Create "Display" section */ - IniSection = IniCacheAppendSection(IniCache, - L"Display"); - - /* TitleText=ReactOS Boot Manager */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TitleText", - L"ReactOS Boot Manager"); - - /* StatusBarColor=Cyan */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"StatusBarColor", - L"Cyan"); - - /* StatusBarTextColor=Black */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"StatusBarTextColor", - L"Black"); - - /* BackdropTextColor=White */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BackdropTextColor", - L"White"); - - /* BackdropColor=Blue */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BackdropColor", - L"Blue"); - - /* BackdropFillStyle=Medium */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BackdropFillStyle", - L"Medium"); - - /* TitleBoxTextColor=White */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TitleBoxTextColor", - L"White"); - - /* TitleBoxColor=Red */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TitleBoxColor", - L"Red"); - - /* MessageBoxTextColor=White */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"MessageBoxTextColor", - L"White"); - - /* MessageBoxColor=Blue */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"MessageBoxColor", - L"Blue"); - - /* MenuTextColor=White */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"MenuTextColor", - L"Gray"); - - /* MenuColor=Blue */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"MenuColor", - L"Black"); - - /* TextColor=Yellow */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TextColor", - L"Gray"); - - /* SelectedTextColor=Black */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"SelectedTextColor", - L"Black"); - - /* SelectedColor=Gray */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"SelectedColor", - L"Gray"); - - /* SelectedColor=Gray */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"ShowTime", - L"No"); + /* Create "Display" section */ + IniSection = IniCacheAppendSection(IniCache, L"Display"); + + /* TitleText=ReactOS Boot Manager */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TitleText", + L"ReactOS Boot Manager"); + + /* StatusBarColor=Cyan */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"StatusBarColor", + L"Cyan"); + + /* StatusBarTextColor=Black */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"StatusBarTextColor", + L"Black"); + + /* BackdropTextColor=White */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BackdropTextColor", + L"White"); + + /* BackdropColor=Blue */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BackdropColor", + L"Blue"); + + /* BackdropFillStyle=Medium */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BackdropFillStyle", + L"Medium"); + + /* TitleBoxTextColor=White */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TitleBoxTextColor", + L"White"); + + /* TitleBoxColor=Red */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TitleBoxColor", + L"Red"); + + /* MessageBoxTextColor=White */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"MessageBoxTextColor", + L"White"); + + /* MessageBoxColor=Blue */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"MessageBoxColor", + L"Blue"); + + /* MenuTextColor=White */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"MenuTextColor", + L"Gray"); + + /* MenuColor=Blue */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"MenuColor", + L"Black"); + + /* TextColor=Yellow */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TextColor", + L"Gray"); + + /* SelectedTextColor=Black */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"SelectedTextColor", + L"Black"); + + /* SelectedColor=Gray */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"SelectedColor", + L"Gray"); /* SelectedColor=Gray */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"MenuBox", - L"No"); + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"ShowTime", + L"No"); + + /* SelectedColor=Gray */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"MenuBox", + L"No"); /* SelectedColor=Gray */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"CenterMenu", - L"No"); + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"CenterMenu", + L"No"); /* SelectedColor=Gray */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"MinimalUI", - L"Yes"); + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"MinimalUI", + L"Yes"); /* SelectedColor=Gray */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"TimeText", - L"Seconds until highlighted choice will be started automatically: "); + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"TimeText", + L"Seconds until highlighted choice will be started automatically: "); } NTSTATUS -CreateFreeLoaderIniForDos(PWCHAR IniPath, - PWCHAR ArcPath) +CreateFreeLoaderIniForDos( + PWCHAR IniPath, + PWCHAR ArcPath) { - PINICACHE IniCache; - PINICACHESECTION IniSection; - - IniCache = IniCacheCreate(); - - CreateCommonFreeLoaderSections(IniCache); - - /* Create "Operating Systems" section */ - IniSection = IniCacheAppendSection(IniCache, - L"Operating Systems"); - - /* REACTOS=ReactOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"ReactOS", - L"\"ReactOS\""); - - /* ReactOS_Debug="ReactOS (Debug)" */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"ReactOS_Debug", - L"\"ReactOS (Debug)\""); - - /* DOS=Dos/Windows */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"DOS", - L"\"DOS/Windows\""); - - /* Create "ReactOS" section */ - IniSection = IniCacheAppendSection(IniCache, - L"ReactOS"); - - /* BootType=ReactOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootType", - L"ReactOS"); - - /* SystemPath= */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"SystemPath", - ArcPath); - - /* Create "ReactOS_Debug" section */ - IniSection = IniCacheAppendSection(IniCache, - L"ReactOS_Debug"); - - /* BootType=ReactOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootType", - L"ReactOS"); - - /* SystemPath= */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"SystemPath", - ArcPath); - - /* Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"Options", - L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS"); - - /* Create "DOS" section */ - IniSection = IniCacheAppendSection(IniCache, - L"DOS"); - - /* BootType=BootSector */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootType", - L"BootSector"); - - /* BootDrive=hd0 */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootDrive", - L"hd0"); - - /* BootPartition=1 */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootPartition", - L"1"); - - /* BootSector=BOOTSECT.DOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootSectorFile", - L"BOOTSECT.DOS"); - - IniCacheSave(IniCache, IniPath); - IniCacheDestroy(IniCache); - - return(STATUS_SUCCESS); + PINICACHE IniCache; + PINICACHESECTION IniSection; + + IniCache = IniCacheCreate(); + + CreateCommonFreeLoaderSections(IniCache); + + /* Create "Operating Systems" section */ + IniSection = IniCacheAppendSection(IniCache, L"Operating Systems"); + + /* REACTOS=ReactOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"ReactOS", + L"\"ReactOS\""); + + /* ReactOS_Debug="ReactOS (Debug)" */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"ReactOS_Debug", + L"\"ReactOS (Debug)\""); + + /* DOS=Dos/Windows */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"DOS", + L"\"DOS/Windows\""); + + /* Create "ReactOS" section */ + IniSection = IniCacheAppendSection(IniCache, L"ReactOS"); + + /* BootType=ReactOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootType", + L"ReactOS"); + + /* SystemPath= */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"SystemPath", + ArcPath); + + /* Create "ReactOS_Debug" section */ + IniSection = IniCacheAppendSection(IniCache, L"ReactOS_Debug"); + + /* BootType=ReactOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootType", + L"ReactOS"); + + /* SystemPath= */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"SystemPath", + ArcPath); + + /* Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"Options", + L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS"); + + /* Create "DOS" section */ + IniSection = IniCacheAppendSection(IniCache, + L"DOS"); + + /* BootType=BootSector */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootType", + L"BootSector"); + + /* BootDrive=hd0 */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootDrive", + L"hd0"); + + /* BootPartition=1 */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootPartition", + L"1"); + + /* BootSector=BOOTSECT.DOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootSectorFile", + L"BOOTSECT.DOS"); + + IniCacheSave(IniCache, IniPath); + IniCacheDestroy(IniCache); + + return STATUS_SUCCESS; } @@ -434,741 +414,257 @@ CreateFreeLoaderEntry( /* Insert entry into "Operating Systems" section */ IniCacheInsertKey(OSSection, - NULL, - INSERT_LAST, - Section, - Description); + NULL, + INSERT_LAST, + Section, + Description); /* Create new section */ IniSection = IniCacheAppendSection(IniCache, Section); /* BootType= */ IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootType", - BootType); + NULL, + INSERT_LAST, + L"BootType", + BootType); /* SystemPath= */ IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"SystemPath", - ArcPath); + NULL, + INSERT_LAST, + L"SystemPath", + ArcPath); /* Options=*/ IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"Options", - Options); + NULL, + INSERT_LAST, + L"Options", + Options); return STATUS_SUCCESS; } NTSTATUS -CreateFreeLoaderIniForReactos(PWCHAR IniPath, - PWCHAR ArcPath) +CreateFreeLoaderIniForReactos( + PWCHAR IniPath, + PWCHAR ArcPath) { - PINICACHE IniCache; - PINICACHESECTION IniSection; + PINICACHE IniCache; + PINICACHESECTION IniSection; - IniCache = IniCacheCreate(); + IniCache = IniCacheCreate(); - CreateCommonFreeLoaderSections(IniCache); + CreateCommonFreeLoaderSections(IniCache); - /* Create "Operating Systems" section */ - IniSection = IniCacheAppendSection(IniCache, - L"Operating Systems"); + /* Create "Operating Systems" section */ + IniSection = IniCacheAppendSection(IniCache, L"Operating Systems"); /* ReactOS */ CreateFreeLoaderEntry(IniCache, IniSection, - L"ReactOS", L"\"ReactOS\"", - L"Windows2003", ArcPath, - L""); + L"ReactOS", L"\"ReactOS\"", + L"Windows2003", ArcPath, + L""); /* ReactOS_Debug */ CreateFreeLoaderEntry(IniCache, IniSection, - L"ReactOS_Debug", L"\"ReactOS (Debug)\"", - L"Windows2003", ArcPath, - L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS"); + L"ReactOS_Debug", L"\"ReactOS (Debug)\"", + L"Windows2003", ArcPath, + L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS"); #if DBG +#ifndef _WINKD_ /* ReactOS_KdSerial */ CreateFreeLoaderEntry(IniCache, IniSection, - L"ReactOS_KdSerial", L"\"ReactOS (RosDbg)\"", - L"Windows2003", ArcPath, - L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL"); + L"ReactOS_KdSerial", L"\"ReactOS (RosDbg)\"", + L"Windows2003", ArcPath, + L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL"); +#endif /* ReactOS_LogFile */ CreateFreeLoaderEntry(IniCache, IniSection, - L"ReactOS_LogFile", L"\"ReactOS (Log file)\"", - L"Windows2003", ArcPath, - L"/DEBUG /DEBUGPORT=FILE /SOS"); + L"ReactOS_LogFile", L"\"ReactOS (Log file)\"", + L"Windows2003", ArcPath, + L"/DEBUG /DEBUGPORT=FILE /SOS"); /* ReactOS_Ram */ CreateFreeLoaderEntry(IniCache, IniSection, - L"ReactOS_Ram", L"\"ReactOS (RAM Disk)\"", - L"ReactOS", L"ramdisk(0)\\ReactOS", - L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDIMAGEPATH=reactos.img /RDIMAGEOFFSET=32256"); + L"ReactOS_Ram", L"\"ReactOS (RAM Disk)\"", + L"ReactOS", L"ramdisk(0)\\ReactOS", + L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDIMAGEPATH=reactos.img /RDIMAGEOFFSET=32256"); #endif - /* Save the ini file */ - IniCacheSave(IniCache, IniPath); - IniCacheDestroy(IniCache); + /* Save the ini file */ + IniCacheSave(IniCache, IniPath); + IniCacheDestroy(IniCache); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } NTSTATUS -UpdateFreeLoaderIni(PWCHAR IniPath, - PWCHAR ArcPath) +UpdateFreeLoaderIni( + PWCHAR IniPath, + PWCHAR ArcPath) { - UNICODE_STRING Name; - PINICACHE IniCache; - PINICACHESECTION IniSection; - PINICACHESECTION OsIniSection; - WCHAR SectionName[80]; - WCHAR OsName[80]; - WCHAR SystemPath[200]; - WCHAR SectionName2[200]; - PWCHAR KeyData; - ULONG i,j; - NTSTATUS Status; - - RtlInitUnicodeString(&Name, - IniPath); - - Status = IniCacheLoad(&IniCache, - &Name, - FALSE); - if (!NT_SUCCESS(Status)) - return(Status); - - /* Get "Operating Systems" section */ - IniSection = IniCacheGetSection(IniCache, - L"Operating Systems"); - if (IniSection == NULL) - { - IniCacheDestroy(IniCache); - return(STATUS_UNSUCCESSFUL); - } - - /* Find an existing usable or an unused section name */ - i = 1; - wcscpy(SectionName, L"ReactOS"); - wcscpy(OsName, L"\"ReactOS\""); - while(TRUE) - { - Status = IniCacheGetKey(IniSection, - SectionName, - &KeyData); + UNICODE_STRING Name; + PINICACHE IniCache; + PINICACHESECTION IniSection; + PINICACHESECTION OsIniSection; + WCHAR SectionName[80]; + WCHAR OsName[80]; + WCHAR SystemPath[200]; + WCHAR SectionName2[200]; + PWCHAR KeyData; + ULONG i,j; + NTSTATUS Status; + + RtlInitUnicodeString(&Name, IniPath); + + Status = IniCacheLoad(&IniCache, &Name, FALSE); if (!NT_SUCCESS(Status)) - break; + return Status; - /* Get operation system section */ - if (KeyData[0] == '"') + /* Get "Operating Systems" section */ + IniSection = IniCacheGetSection(IniCache, L"Operating Systems"); + if (IniSection == NULL) { - wcscpy(SectionName2, &KeyData[1]); - j = wcslen(SectionName2); - if (j > 0) - { - SectionName2[j-1] = 0; - } - } - else - { - wcscpy(SectionName2, KeyData); + IniCacheDestroy(IniCache); + return STATUS_UNSUCCESSFUL; } - OsIniSection = IniCacheGetSection(IniCache, - SectionName2); - if (OsIniSection != NULL) + /* Find an existing usable or an unused section name */ + i = 1; + wcscpy(SectionName, L"ReactOS"); + wcscpy(OsName, L"\"ReactOS\""); + while(TRUE) { - BOOLEAN UseExistingEntry = TRUE; + Status = IniCacheGetKey(IniSection, SectionName, &KeyData); + if (!NT_SUCCESS(Status)) + break; - /* Check BootType */ - Status = IniCacheGetKey(OsIniSection, - L"BootType", - &KeyData); - if (NT_SUCCESS(Status)) - { - if (KeyData == NULL - || (_wcsicmp(KeyData, L"ReactOS") != 0 - && _wcsicmp(KeyData, L"\"ReactOS\"") != 0)) + /* Get operation system section */ + if (KeyData[0] == '"') { - /* This is not a ReactOS entry */ - UseExistingEntry = FALSE; - } - } - else - { - UseExistingEntry = FALSE; - } - - if (UseExistingEntry) - { - /* BootType is ReactOS. Now check SystemPath */ - Status = IniCacheGetKey(OsIniSection, - L"SystemPath", - &KeyData); - if (NT_SUCCESS(Status)) - { - swprintf(SystemPath, L"\"%S\"", ArcPath); - if (KeyData == NULL - || (_wcsicmp(KeyData, ArcPath) != 0 - && _wcsicmp(KeyData, SystemPath) != 0)) - { - /* This entry is a ReactOS entry, but the SystemRoot does not - match the one we are looking for */ - UseExistingEntry = FALSE; - } + wcscpy(SectionName2, &KeyData[1]); + j = wcslen(SectionName2); + if (j > 0) + { + SectionName2[j-1] = 0; + } } else { - UseExistingEntry = FALSE; + wcscpy(SectionName2, KeyData); } - } - - if (UseExistingEntry) - { - IniCacheDestroy(IniCache); - return(STATUS_SUCCESS); - } - } - - swprintf(SectionName, L"ReactOS_%lu", i); - swprintf(OsName, L"\"ReactOS %lu\"", i); - i++; - } - - /* = */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - SectionName, - OsName); - - /* Create section */ - IniSection = IniCacheAppendSection(IniCache, - SectionName); - - /* BootType=ReactOS */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"BootType", - L"ReactOS"); - - /* SystemPath= */ - IniCacheInsertKey(IniSection, - NULL, - INSERT_LAST, - L"SystemPath", - ArcPath); - - IniCacheSave(IniCache, IniPath); - IniCacheDestroy(IniCache); - - return(STATUS_SUCCESS); -} - -NTSTATUS -SaveCurrentBootSector(PWSTR RootPath, - PWSTR DstPath) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - HANDLE FileHandle; - NTSTATUS Status; - PUCHAR BootSector; - - /* Allocate buffer for bootsector */ - BootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (BootSector == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); - - /* Read current boot sector into buffer */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, BootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - BootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, BootSector); - return(Status); - } - - /* Write bootsector to DstPath */ - RtlInitUnicodeString(&Name, - DstPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtCreateFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_SUPERSEDE, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, BootSector); - return(Status); - } - - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - BootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - - /* Free the new boot sector */ - RtlFreeHeap(ProcessHeap, 0, BootSector); - - return(Status); -} + OsIniSection = IniCacheGetSection(IniCache, SectionName2); + if (OsIniSection != NULL) + { + BOOLEAN UseExistingEntry = TRUE; + + /* Check BootType */ + Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData); + if (NT_SUCCESS(Status)) + { + if ((KeyData == NULL) || + ( (_wcsicmp(KeyData, L"ReactOS") != 0) && + (_wcsicmp(KeyData, L"\"ReactOS\"") != 0) )) + { + /* This is not a ReactOS entry */ + UseExistingEntry = FALSE; + } + } + else + { + UseExistingEntry = FALSE; + } + + if (UseExistingEntry) + { + /* BootType is ReactOS. Now check SystemPath */ + Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData); + if (NT_SUCCESS(Status)) + { + swprintf(SystemPath, L"\"%S\"", ArcPath); + if ((KeyData == NULL) || + ((_wcsicmp(KeyData, ArcPath) != 0) && + (_wcsicmp(KeyData, SystemPath) != 0) )) + { + /* This entry is a ReactOS entry, but the SystemRoot does not + match the one we are looking for */ + UseExistingEntry = FALSE; + } + } + else + { + UseExistingEntry = FALSE; + } + } + + if (UseExistingEntry) + { + IniCacheDestroy(IniCache); + return STATUS_SUCCESS; + } + } + swprintf(SectionName, L"ReactOS_%lu", i); + swprintf(OsName, L"\"ReactOS %lu\"", i); + i++; + } -NTSTATUS -InstallFat16BootCodeToFile(PWSTR SrcPath, - PWSTR DstPath, - PWSTR RootPath) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - HANDLE FileHandle; - NTSTATUS Status; - PUCHAR OrigBootSector; - PUCHAR NewBootSector; - - /* Allocate buffer for original bootsector */ - OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (OrigBootSector == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); - - /* Read current boot sector into buffer */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - OrigBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } + /* = */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + SectionName, + OsName); + /* Create section */ + IniSection = IniCacheAppendSection(IniCache, SectionName); - /* Allocate buffer for new bootsector */ - NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (NewBootSector == NULL) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - /* Read new bootsector from SrcPath */ - RtlInitUnicodeString(&Name, - SrcPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Adjust bootsector (copy a part of the FAT BPB) */ - memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/); - - /* Free the original boot sector */ - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - - /* Write new bootsector to DstPath */ - RtlInitUnicodeString(&Name, - DstPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtCreateFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_OVERWRITE_IF, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } + /* BootType=ReactOS */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"BootType", + L"ReactOS"); -#if 0 - FilePosition.QuadPart = 0; -#endif - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - - /* Free the new boot sector */ - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - - return(Status); -} + /* SystemPath= */ + IniCacheInsertKey(IniSection, + NULL, + INSERT_LAST, + L"SystemPath", + ArcPath); + IniCacheSave(IniCache, IniPath); + IniCacheDestroy(IniCache); -NTSTATUS -InstallFat32BootCodeToFile(PWSTR SrcPath, - PWSTR DstPath, - PWSTR RootPath) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - HANDLE FileHandle; - NTSTATUS Status; - PUCHAR OrigBootSector; - PUCHAR NewBootSector; - LARGE_INTEGER FileOffset; - - /* Allocate buffer for original bootsector */ - OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (OrigBootSector == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); - - /* Read current boot sector into buffer */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - OrigBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - /* Allocate buffer for new bootsector (2 sectors) */ - NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, - 0, - 2 * SECTORSIZE); - if (NewBootSector == NULL) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - /* Read new bootsector from SrcPath */ - RtlInitUnicodeString(&Name, - SrcPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - 2 * SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Adjust bootsector (copy a part of the FAT32 BPB) */ - memcpy((NewBootSector + 3), - (OrigBootSector + 3), - 87); /* FAT32 BPB length */ - - /* Disable the backup boot sector */ - NewBootSector[0x32] = 0x00; - NewBootSector[0x33] = 0x00; - - /* Free the original boot sector */ - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - - /* Write the first sector of the new bootcode to DstPath */ - RtlInitUnicodeString(&Name, - DstPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtCreateFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_SUPERSEDE, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Write the second sector of the new bootcode to boot disk sector 14 */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE); - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - (NewBootSector + SECTORSIZE), - SECTORSIZE, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - } - NtClose(FileHandle); - - /* Free the new boot sector */ - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - - return(Status); + return STATUS_SUCCESS; } NTSTATUS -InstallMbrBootCodeToDisk (PWSTR SrcPath, - PWSTR RootPath) +SaveCurrentBootSector( + PWSTR RootPath, + PWSTR DstPath) { OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING Name; HANDLE FileHandle; NTSTATUS Status; - PPARTITION_SECTOR OrigBootSector; - PPARTITION_SECTOR NewBootSector; + PUCHAR BootSector; - /* Allocate buffer for original bootsector */ - OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(PARTITION_SECTOR)); - if (OrigBootSector == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); + /* Allocate buffer for bootsector */ + BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); + if (BootSector == NULL) + return STATUS_INSUFFICIENT_RESOURCES; /* Read current boot sector into buffer */ - RtlInitUnicodeString(&Name, - RootPath); + RtlInitUnicodeString(&Name, RootPath); InitializeObjectAttributes(&ObjectAttributes, &Name, @@ -1182,1050 +678,1502 @@ InstallMbrBootCodeToDisk (PWSTR SrcPath, &IoStatusBlock, 0, FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, BootSector); + return Status; + } Status = NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, - OrigBootSector, + BootSector, SECTORSIZE, NULL, NULL); NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - - /* Allocate buffer for new bootsector */ - NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(PARTITION_SECTOR)); - if (NewBootSector == NULL) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - /* Read new bootsector from SrcPath */ - RtlInitUnicodeString(&Name, - SrcPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - sizeof(PARTITION_SECTOR), - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Copy partition table from old MBR to new */ - RtlCopyMemory (&NewBootSector->Signature, - &OrigBootSector->Signature, - sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */); - - /* Free the original boot sector */ - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - - /* Write new bootsector to RootPath */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - - /* Free the new boot sector */ - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - - return(Status); -} - - -NTSTATUS -InstallFat16BootCodeToDisk(PWSTR SrcPath, - PWSTR RootPath) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - HANDLE FileHandle; - NTSTATUS Status; - PFAT_BOOTSECTOR OrigBootSector; - PFAT_BOOTSECTOR NewBootSector; - PARTITION_INFORMATION *PartInfo; - - /* Allocate buffer for original bootsector */ - OrigBootSector = RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (OrigBootSector == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); - - /* Read current boot sector into buffer */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - OrigBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - - /* Allocate buffer for new bootsector */ - NewBootSector = RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (NewBootSector == NULL) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - /* Read new bootsector from SrcPath */ - RtlInitUnicodeString(&Name, - SrcPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Adjust bootsector (copy a part of the FAT16 BPB) */ - memcpy(&NewBootSector->BytesPerSector, - &OrigBootSector->BytesPerSector, - 51); /* FAT16 BPB length */ - - PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber]; - NewBootSector->HiddenSectors = PartInfo->HiddenSectors; - - /* Free the original boot sector */ - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - - /* Write new bootsector to RootPath */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - -#if 0 - FilePosition.QuadPart = 0; -#endif - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - - /* Free the new boot sector */ - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - - return(Status); -} - - -NTSTATUS -InstallFat32BootCodeToDisk(PWSTR SrcPath, - PWSTR RootPath) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - HANDLE FileHandle; - NTSTATUS Status; - PFAT32_BOOTSECTOR OrigBootSector; - PFAT32_BOOTSECTOR NewBootSector; - LARGE_INTEGER FileOffset; - USHORT BackupBootSector; - PARTITION_INFORMATION *PartInfo; - - /* Allocate buffer for original bootsector */ - OrigBootSector = RtlAllocateHeap(ProcessHeap, - 0, - SECTORSIZE); - if (OrigBootSector == NULL) - return(STATUS_INSUFFICIENT_RESOURCES); - - /* Read current boot sector into buffer */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - OrigBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(Status); - } + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, BootSector); + return Status; + } + /* Write bootsector to DstPath */ + RtlInitUnicodeString(&Name, DstPath); - /* Allocate buffer for new bootsector (2 sectors) */ - NewBootSector = RtlAllocateHeap(ProcessHeap, - 0, - 2 * SECTORSIZE); - if (NewBootSector == NULL) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - /* Read new bootsector from SrcPath */ - RtlInitUnicodeString(&Name, - SrcPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - 2 * SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Adjust bootsector (copy a part of the FAT32 BPB) */ - memcpy(&NewBootSector->BytesPerSector, - &OrigBootSector->BytesPerSector, - 79); /* FAT32 BPB length */ - - PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber]; - NewBootSector->HiddenSectors = PartInfo->HiddenSectors; - - /* Get the location of the backup boot sector */ - BackupBootSector = OrigBootSector->BackupBootSector; - - /* Free the original boot sector */ - RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - - /* Write the first sector of the new bootcode to DstPath */ - RtlInitUnicodeString(&Name, - RootPath); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - - /* Write sector 0 */ - FileOffset.QuadPart = 0ULL; - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); - /* Write backup boot sector */ - if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF)) - { - FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE); - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - NewBootSector, - SECTORSIZE, - &FileOffset, - NULL); + Status = NtCreateFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, + NULL, + 0); if (!NT_SUCCESS(Status)) { - DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - return(Status); - } - } - - /* Write sector 14 */ - FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE); - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - ((PUCHAR)NewBootSector + SECTORSIZE), - SECTORSIZE, - &FileOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); - } - NtClose(FileHandle); - - /* Free the new boot sector */ - RtlFreeHeap(ProcessHeap, 0, NewBootSector); - - return(Status); -} - + RtlFreeHeap(ProcessHeap, 0, BootSector); + return Status; + } -static NTSTATUS -UnprotectBootIni(PWSTR FileName, - PULONG Attributes) -{ - UNICODE_STRING Name; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - FILE_BASIC_INFORMATION FileInfo; - HANDLE FileHandle; - NTSTATUS Status; - - RtlInitUnicodeString(&Name, - FileName); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ|GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (Status == STATUS_NO_SUCH_FILE) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - *Attributes = 0; - return(STATUS_SUCCESS); - } - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - return(Status); - } - - Status = NtQueryInformationFile(FileHandle, - &IoStatusBlock, - &FileInfo, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + BootSector, + SECTORSIZE, + NULL, + NULL); NtClose(FileHandle); - return(Status); - } - - *Attributes = FileInfo.FileAttributes; - - /* Delete attributes SYSTEM, HIDDEN and READONLY */ - FileInfo.FileAttributes = FileInfo.FileAttributes & - ~(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY); - - Status = NtSetInformationFile(FileHandle, - &IoStatusBlock, - &FileInfo, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status); - } - - NtClose(FileHandle); - return(Status); -} + /* Free the new boot sector */ + RtlFreeHeap(ProcessHeap, 0, BootSector); -static NTSTATUS -ProtectBootIni(PWSTR FileName, - ULONG Attributes) -{ - UNICODE_STRING Name; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - FILE_BASIC_INFORMATION FileInfo; - HANDLE FileHandle; - NTSTATUS Status; - - RtlInitUnicodeString(&Name, - FileName); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - GENERIC_READ|GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - return(Status); - } - - Status = NtQueryInformationFile(FileHandle, - &IoStatusBlock, - &FileInfo, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); - return(Status); - } - - FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes; - - Status = NtSetInformationFile(FileHandle, - &IoStatusBlock, - &FileInfo, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status); - } - - NtClose(FileHandle); - return(Status); + return Status; } NTSTATUS -UpdateBootIni(PWSTR BootIniPath, - PWSTR EntryName, - PWSTR EntryValue) +InstallFat16BootCodeToFile( + PWSTR SrcPath, + PWSTR DstPath, + PWSTR RootPath) { - UNICODE_STRING Name; - PINICACHE Cache = NULL; - PINICACHESECTION Section = NULL; - NTSTATUS Status; - ULONG FileAttribute; - PWCHAR OldValue = NULL; - - RtlInitUnicodeString(&Name, - BootIniPath); - - Status = IniCacheLoad(&Cache, - &Name, - FALSE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Section = IniCacheGetSection(Cache, - L"operating systems"); - if (Section == NULL) - { - IniCacheDestroy(Cache); - return(STATUS_UNSUCCESSFUL); - } - - /* Check - maybe record already exists */ - Status = IniCacheGetKey(Section, - EntryName, - &OldValue); - - /* If either key was not found, or contains something else - add new one */ - if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue)) - { - IniCacheInsertKey(Section, - NULL, - INSERT_LAST, - EntryName, - EntryValue); - } - - Status = UnprotectBootIni(BootIniPath, - &FileAttribute); - if (!NT_SUCCESS(Status)) - { - IniCacheDestroy(Cache); - return(Status); - } - - Status = IniCacheSave(Cache, - BootIniPath); - if (!NT_SUCCESS(Status)) - { - IniCacheDestroy(Cache); - return(Status); - } + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + HANDLE FileHandle; + NTSTATUS Status; + PFAT_BOOTSECTOR OrigBootSector; + PFAT_BOOTSECTOR NewBootSector; - FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY); - Status = ProtectBootIni(BootIniPath, - FileAttribute); + /* Allocate buffer for original bootsector */ + OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); + if (OrigBootSector == NULL) + return STATUS_INSUFFICIENT_RESOURCES ; - IniCacheDestroy(Cache); + /* Read current boot sector into buffer */ + RtlInitUnicodeString(&Name, RootPath); - return(Status); -} + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); -BOOLEAN -CheckInstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath) -{ -#ifdef __REACTOS__ - if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") || - DoesFileExist(SystemRootPath->Buffer, L"boot.ini")) + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) { - return TRUE; + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; } - else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") || - DoesFileExist(SystemRootPath->Buffer, L"msdos.sys")) + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + OrigBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) { - return TRUE; + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; } -#endif - return FALSE; -} + /* Allocate buffer for new bootsector */ + NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); + if (NewBootSector == NULL) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return STATUS_INSUFFICIENT_RESOURCES; + } + /* Read new bootsector from SrcPath */ + RtlInitUnicodeString(&Name, SrcPath); -NTSTATUS -InstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath, - PUNICODE_STRING SourceRootPath, - PUNICODE_STRING DestinationArcPath, - UCHAR PartitionType) + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Adjust bootsector (copy a part of the FAT BPB) */ + memcpy(&NewBootSector->OemName, + &OrigBootSector->OemName, + FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) - + FIELD_OFFSET(FAT_BOOTSECTOR, OemName)); + + /* Free the original boot sector */ + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + + /* Write new bootsector to DstPath */ + RtlInitUnicodeString(&Name, DstPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtCreateFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OVERWRITE_IF, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + +#if 0 + FilePosition.QuadPart = 0; +#endif + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + + /* Free the new boot sector */ + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + + return Status; +} + + +NTSTATUS +InstallFat32BootCodeToFile( + PWSTR SrcPath, + PWSTR DstPath, + PWSTR RootPath) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + HANDLE FileHandle; + NTSTATUS Status; + PFAT32_BOOTSECTOR OrigBootSector; + PFAT32_BOOTSECTOR NewBootSector; + LARGE_INTEGER FileOffset; + + /* Allocate buffer for original bootsector */ + OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); + if (OrigBootSector == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + /* Read current boot sector into buffer */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + OrigBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + /* Allocate buffer for new bootsector (2 sectors) */ + NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE); + if (NewBootSector == NULL) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Read new bootsector from SrcPath */ + RtlInitUnicodeString(&Name, SrcPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + 2 * SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Adjust bootsector (copy a part of the FAT32 BPB) */ + memcpy(&NewBootSector->OemName, + &OrigBootSector->OemName, + FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) - + FIELD_OFFSET(FAT32_BOOTSECTOR, OemName)); + + /* Disable the backup boot sector */ + NewBootSector->BackupBootSector = 0; + + /* Free the original boot sector */ + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + + /* Write the first sector of the new bootcode to DstPath */ + RtlInitUnicodeString(&Name, DstPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtCreateFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Write the second sector of the new bootcode to boot disk sector 14 */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + (NewBootSector + SECTORSIZE), + SECTORSIZE, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + } + NtClose(FileHandle); + + /* Free the new boot sector */ + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + + return Status; +} + + +NTSTATUS +InstallMbrBootCodeToDisk( + PWSTR SrcPath, + PWSTR RootPath) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + HANDLE FileHandle; + NTSTATUS Status; + PPARTITION_SECTOR OrigBootSector; + PPARTITION_SECTOR NewBootSector; + + /* Allocate buffer for original bootsector */ + OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(PARTITION_SECTOR)); + if (OrigBootSector == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + /* Read current boot sector into buffer */ + RtlInitUnicodeString(&Name, + RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + OrigBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + + /* Allocate buffer for new bootsector */ + NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(PARTITION_SECTOR)); + if (NewBootSector == NULL) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Read new bootsector from SrcPath */ + RtlInitUnicodeString(&Name, SrcPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + sizeof(PARTITION_SECTOR), + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Copy partition table from old MBR to new */ + RtlCopyMemory (&NewBootSector->Signature, + &OrigBootSector->Signature, + sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */); + + /* Free the original boot sector */ + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + + /* Write new bootsector to RootPath */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + + /* Free the new boot sector */ + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + + return Status; +} + + +NTSTATUS +InstallFat16BootCodeToDisk( + PWSTR SrcPath, + PWSTR RootPath) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + HANDLE FileHandle; + NTSTATUS Status; + PFAT_BOOTSECTOR OrigBootSector; + PFAT_BOOTSECTOR NewBootSector; + PARTITION_INFORMATION *PartInfo; + + /* Allocate buffer for original bootsector */ + OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); + if (OrigBootSector == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + /* Read current boot sector into buffer */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + OrigBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + + /* Allocate buffer for new bootsector */ + NewBootSector = RtlAllocateHeap(ProcessHeap, + 0, + SECTORSIZE); + if (NewBootSector == NULL) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Read new bootsector from SrcPath */ + RtlInitUnicodeString(&Name, SrcPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Adjust bootsector (copy a part of the FAT16 BPB) */ + memcpy(&NewBootSector->OemName, + &OrigBootSector->OemName, + FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) - + FIELD_OFFSET(FAT_BOOTSECTOR, OemName)); + + PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber]; + NewBootSector->HiddenSectors = PartInfo->HiddenSectors; + + /* Free the original boot sector */ + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + + /* Write new bootsector to RootPath */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + +#if 0 + FilePosition.QuadPart = 0; +#endif + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + + /* Free the new boot sector */ + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + + return Status; +} + + +NTSTATUS +InstallFat32BootCodeToDisk( + PWSTR SrcPath, + PWSTR RootPath) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + HANDLE FileHandle; + NTSTATUS Status; + PFAT32_BOOTSECTOR OrigBootSector; + PFAT32_BOOTSECTOR NewBootSector; + LARGE_INTEGER FileOffset; + USHORT BackupBootSector; + PARTITION_INFORMATION *PartInfo; + + /* Allocate buffer for original bootsector */ + OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); + if (OrigBootSector == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + /* Read current boot sector into buffer */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + OrigBootSector, + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return Status; + } + + + /* Allocate buffer for new bootsector (2 sectors) */ + NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE); + if (NewBootSector == NULL) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Read new bootsector from SrcPath */ + RtlInitUnicodeString(&Name, SrcPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + 2 * SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Adjust bootsector (copy a part of the FAT32 BPB) */ + memcpy(&NewBootSector->OemName, + &OrigBootSector->OemName, + FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) - + FIELD_OFFSET(FAT32_BOOTSECTOR, OemName)); + + PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber]; + NewBootSector->HiddenSectors = PartInfo->HiddenSectors; + + /* Get the location of the backup boot sector */ + BackupBootSector = OrigBootSector->BackupBootSector; + + /* Free the original boot sector */ + RtlFreeHeap(ProcessHeap, 0, OrigBootSector); + + /* Write the first sector of the new bootcode to DstPath */ + RtlInitUnicodeString(&Name, RootPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Write sector 0 */ + FileOffset.QuadPart = 0ULL; + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); + NtClose(FileHandle); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + + /* Write backup boot sector */ + if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF)) + { + FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + SECTORSIZE, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); + NtClose(FileHandle); + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + return Status; + } + } + + /* Write sector 14 */ + FileOffset.QuadPart = 14 * SECTORSIZE; + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + ((PUCHAR)NewBootSector + SECTORSIZE), + SECTORSIZE, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); + } + NtClose(FileHandle); + + /* Free the new boot sector */ + RtlFreeHeap(ProcessHeap, 0, NewBootSector); + + return Status; +} + + +static +NTSTATUS +UnprotectBootIni( + PWSTR FileName, + PULONG Attributes) +{ + UNICODE_STRING Name; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileInfo; + HANDLE FileHandle; + NTSTATUS Status; + + RtlInitUnicodeString(&Name, FileName); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ|GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (Status == STATUS_NO_SUCH_FILE) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + *Attributes = 0; + return STATUS_SUCCESS; + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + return Status; + } + + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileInfo, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status); + NtClose(FileHandle); + return Status; + } + + *Attributes = FileInfo.FileAttributes; + + /* Delete attributes SYSTEM, HIDDEN and READONLY */ + FileInfo.FileAttributes = FileInfo.FileAttributes & + ~(FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_READONLY); + + Status = NtSetInformationFile(FileHandle, + &IoStatusBlock, + &FileInfo, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status); + } + + NtClose(FileHandle); + return Status; +} + + +static +NTSTATUS +ProtectBootIni( + PWSTR FileName, + ULONG Attributes) +{ + UNICODE_STRING Name; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileInfo; + HANDLE FileHandle; + NTSTATUS Status; + + RtlInitUnicodeString(&Name, FileName); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ|GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + return Status; + } + + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileInfo, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status); + NtClose(FileHandle); + return Status; + } + + FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes; + + Status = NtSetInformationFile(FileHandle, + &IoStatusBlock, + &FileInfo, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status); + } + + NtClose(FileHandle); + return Status; +} + + +NTSTATUS +UpdateBootIni( + PWSTR BootIniPath, + PWSTR EntryName, + PWSTR EntryValue) +{ + UNICODE_STRING Name; + PINICACHE Cache = NULL; + PINICACHESECTION Section = NULL; + NTSTATUS Status; + ULONG FileAttribute; + PWCHAR OldValue = NULL; + + RtlInitUnicodeString(&Name, BootIniPath); + + Status = IniCacheLoad(&Cache, &Name, FALSE); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Section = IniCacheGetSection(Cache, + L"operating systems"); + if (Section == NULL) + { + IniCacheDestroy(Cache); + return STATUS_UNSUCCESSFUL; + } + + /* Check - maybe record already exists */ + Status = IniCacheGetKey(Section, EntryName, &OldValue); + + /* If either key was not found, or contains something else - add new one */ + if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue)) + { + IniCacheInsertKey(Section, + NULL, + INSERT_LAST, + EntryName, + EntryValue); + } + + Status = UnprotectBootIni(BootIniPath, + &FileAttribute); + if (!NT_SUCCESS(Status)) + { + IniCacheDestroy(Cache); + return Status; + } + + Status = IniCacheSave(Cache, BootIniPath); + if (!NT_SUCCESS(Status)) + { + IniCacheDestroy(Cache); + return Status; + } + + FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY); + Status = ProtectBootIni(BootIniPath, FileAttribute); + + IniCacheDestroy(Cache); + + return Status; +} + +BOOLEAN +CheckInstallFatBootcodeToPartition( + PUNICODE_STRING SystemRootPath) +{ +#ifdef __REACTOS__ + if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") || + DoesFileExist(SystemRootPath->Buffer, L"boot.ini")) + { + return TRUE; + } + else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") || + DoesFileExist(SystemRootPath->Buffer, L"msdos.sys")) + { + return TRUE; + } +#endif + + return FALSE; +} + + +NTSTATUS +InstallFatBootcodeToPartition( + PUNICODE_STRING SystemRootPath, + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING DestinationArcPath, + UCHAR PartitionType) { #ifdef __REACTOS__ - WCHAR SrcPath[MAX_PATH]; - WCHAR DstPath[MAX_PATH]; - NTSTATUS Status; - - /* FAT or FAT32 partition */ - DPRINT("System path: '%wZ'\n", SystemRootPath); - - if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE || - DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE) - { - /* Search root directory for 'ntldr' and 'boot.ini'. */ - DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n"); - - /* Copy FreeLoader to the boot partition */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\freeldr.sys"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.sys"); - - DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); - Status = SetupCopyFile(SrcPath, DstPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); - return Status; - } - - /* Create or update freeldr.ini */ - if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE) - { - /* Create new 'freeldr.ini' */ - DPRINT1("Create new 'freeldr.ini'\n"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.ini"); - - Status = CreateFreeLoaderIniForReactos(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status); - return Status; - } - - /* Install new bootcode */ - if (PartitionType == PARTITION_FAT32 || - PartitionType == PARTITION_FAT32_XINT13) - { - /* Install FAT32 bootcode */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat32.bin"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\bootsect.ros"); - - DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath); - Status = InstallFat32BootCodeToFile(SrcPath, - DstPath, - SystemRootPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status); - return Status; - } - } - else - { - /* Install FAT16 bootcode */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat.bin"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\bootsect.ros"); - - DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); - Status = InstallFat16BootCodeToFile(SrcPath, - DstPath, - SystemRootPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status); - return Status; - } - } - } - else - { - /* Update existing 'freeldr.ini' */ - DPRINT1("Update existing 'freeldr.ini'\n"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.ini"); - - Status = UpdateFreeLoaderIni(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); - return Status; - } - } - - /* Update 'boot.ini' */ - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\boot.ini"); - - DPRINT1("Update 'boot.ini': %S\n", DstPath); - Status = UpdateBootIni(DstPath, - L"C:\\bootsect.ros", - L"\"ReactOS\""); - if (!NT_SUCCESS(Status)) - { - DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status); - return Status; - } - } - else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE || - DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE) - { - /* Search for root directory for 'io.sys' and 'msdos.sys'. */ - DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n"); - - /* Copy FreeLoader to the boot partition */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\freeldr.sys"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.sys"); - - DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); - Status = SetupCopyFile(SrcPath, DstPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); - return Status; - } - - /* Create or update 'freeldr.ini' */ - if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE) - { - /* Create new 'freeldr.ini' */ - DPRINT1("Create new 'freeldr.ini'\n"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.ini"); - - Status = CreateFreeLoaderIniForDos(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status); - return Status; - } - - /* Save current bootsector as 'BOOTSECT.DOS' */ - wcscpy(SrcPath, SystemRootPath->Buffer); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\bootsect.dos"); - - DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath); - Status = SaveCurrentBootSector(SrcPath, - DstPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status); - return Status; - } - - /* Install new bootsector */ - if (PartitionType == PARTITION_FAT32 || - PartitionType == PARTITION_FAT32_XINT13) - { - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat32.bin"); - - DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); - Status = InstallFat32BootCodeToDisk(SrcPath, - SystemRootPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status); - return Status; - } - } - else - { - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat.bin"); - - DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); - Status = InstallFat16BootCodeToDisk(SrcPath, - SystemRootPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); - return Status; - } - } - } - else - { - /* Update existing 'freeldr.ini' */ - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.ini"); - - Status = UpdateFreeLoaderIni(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); - return Status; - } - } - } - else - { - /* No or unknown boot loader */ - DPRINT1("No or unknown boot loader found\n"); - - /* Copy FreeLoader to the boot partition */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\freeldr.sys"); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.sys"); - - DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); - Status = SetupCopyFile(SrcPath, DstPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); - return Status; - } - - /* Create or update 'freeldr.ini' */ - if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE) - { - /* Create new freeldr.ini */ - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.ini"); - - DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); - Status = CreateFreeLoaderIniForReactos(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status); - return Status; - } - - /* Save current bootsector as 'BOOTSECT.OLD' */ - wcscpy(SrcPath, SystemRootPath->Buffer); - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\bootsect.old"); - - DPRINT("Save bootsector: %S ==> %S\n", SrcPath, DstPath); - Status = SaveCurrentBootSector(SrcPath, - DstPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status); - return Status; - } - - /* Install new bootsector */ - if (PartitionType == PARTITION_FAT32 || - PartitionType == PARTITION_FAT32_XINT13) - { - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat32.bin"); - - DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); - Status = InstallFat32BootCodeToDisk(SrcPath, - SystemRootPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status); - return Status; - } - } - else - { - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat.bin"); - - DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); - Status = InstallFat16BootCodeToDisk(SrcPath, - SystemRootPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); - return Status; - } - } - } - else - { - /* Update existing 'freeldr.ini' */ - wcscpy(DstPath, SystemRootPath->Buffer); - wcscat(DstPath, L"\\freeldr.ini"); - - Status = UpdateFreeLoaderIni(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); - return Status; - } - } - } - - return STATUS_SUCCESS; + WCHAR SrcPath[MAX_PATH]; + WCHAR DstPath[MAX_PATH]; + NTSTATUS Status; + + /* FAT or FAT32 partition */ + DPRINT("System path: '%wZ'\n", SystemRootPath); + + if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE || + DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE) + { + /* Search root directory for 'ntldr' and 'boot.ini'. */ + DPRINT("Found Microsoft Windows NT/2000/XP boot loader\n"); + + /* Copy FreeLoader to the boot partition */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\freeldr.sys"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.sys"); + + DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); + Status = SetupCopyFile(SrcPath, DstPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); + return Status; + } + + /* Create or update freeldr.ini */ + if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE) + { + /* Create new 'freeldr.ini' */ + DPRINT1("Create new 'freeldr.ini'\n"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.ini"); + + Status = CreateFreeLoaderIniForReactos(DstPath, + DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status); + return Status; + } + + /* Install new bootcode */ + if (PartitionType == PARTITION_FAT32 || + PartitionType == PARTITION_FAT32_XINT13) + { + /* Install FAT32 bootcode */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat32.bin"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\bootsect.ros"); + + DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath); + Status = InstallFat32BootCodeToFile(SrcPath, + DstPath, + SystemRootPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status); + return Status; + } + } + else + { + /* Install FAT16 bootcode */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat.bin"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\bootsect.ros"); + + DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); + Status = InstallFat16BootCodeToFile(SrcPath, + DstPath, + SystemRootPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status); + return Status; + } + } + } + else + { + /* Update existing 'freeldr.ini' */ + DPRINT1("Update existing 'freeldr.ini'\n"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.ini"); + + Status = UpdateFreeLoaderIni(DstPath, + DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); + return Status; + } + } + + /* Update 'boot.ini' */ + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\boot.ini"); + + DPRINT1("Update 'boot.ini': %S\n", DstPath); + Status = UpdateBootIni(DstPath, + L"C:\\bootsect.ros", + L"\"ReactOS\""); + if (!NT_SUCCESS(Status)) + { + DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status); + return Status; + } + } + else if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE || + DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE) + { + /* Search for root directory for 'io.sys' and 'msdos.sys'. */ + DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n"); + + /* Copy FreeLoader to the boot partition */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\freeldr.sys"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.sys"); + + DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); + Status = SetupCopyFile(SrcPath, DstPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); + return Status; + } + + /* Create or update 'freeldr.ini' */ + if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE) + { + /* Create new 'freeldr.ini' */ + DPRINT1("Create new 'freeldr.ini'\n"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.ini"); + + Status = CreateFreeLoaderIniForDos(DstPath, + DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CreateFreeLoaderIniForDos() failed (Status %lx)\n", Status); + return Status; + } + + /* Save current bootsector as 'BOOTSECT.DOS' */ + wcscpy(SrcPath, SystemRootPath->Buffer); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\bootsect.dos"); + + DPRINT1("Save bootsector: %S ==> %S\n", SrcPath, DstPath); + Status = SaveCurrentBootSector(SrcPath, + DstPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status); + return Status; + } + + /* Install new bootsector */ + if (PartitionType == PARTITION_FAT32 || + PartitionType == PARTITION_FAT32_XINT13) + { + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat32.bin"); + + DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); + Status = InstallFat32BootCodeToDisk(SrcPath, + SystemRootPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status); + return Status; + } + } + else + { + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat.bin"); + + DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); + Status = InstallFat16BootCodeToDisk(SrcPath, + SystemRootPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); + return Status; + } + } + } + else + { + /* Update existing 'freeldr.ini' */ + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.ini"); + + Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); + return Status; + } + } + } + else + { + /* No or unknown boot loader */ + DPRINT1("No or unknown boot loader found\n"); + + /* Copy FreeLoader to the boot partition */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\freeldr.sys"); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.sys"); + + DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); + Status = SetupCopyFile(SrcPath, DstPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); + return Status; + } + + /* Create or update 'freeldr.ini' */ + if (DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini") == FALSE) + { + /* Create new freeldr.ini */ + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.ini"); + + DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); + Status = CreateFreeLoaderIniForReactos(DstPath, + DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status); + return Status; + } + + /* Save current bootsector as 'BOOTSECT.OLD' */ + wcscpy(SrcPath, SystemRootPath->Buffer); + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\bootsect.old"); + + DPRINT("Save bootsector: %S ==> %S\n", SrcPath, DstPath); + Status = SaveCurrentBootSector(SrcPath, + DstPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SaveCurrentBootSector() failed (Status %lx)\n", Status); + return Status; + } + + /* Install new bootsector */ + if ((PartitionType == PARTITION_FAT32) || + (PartitionType == PARTITION_FAT32_XINT13)) + { + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat32.bin"); + + DPRINT("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); + Status = InstallFat32BootCodeToDisk(SrcPath, + SystemRootPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status); + return Status; + } + } + else + { + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat.bin"); + + DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer); + Status = InstallFat16BootCodeToDisk(SrcPath, + SystemRootPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); + return Status; + } + } + } + else + { + /* Update existing 'freeldr.ini' */ + wcscpy(DstPath, SystemRootPath->Buffer); + wcscat(DstPath, L"\\freeldr.ini"); + + Status = UpdateFreeLoaderIni(DstPath, + DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status); + return Status; + } + } + } + + return STATUS_SUCCESS; #else - return STATUS_NOT_IMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; #endif } NTSTATUS -InstallVBRToPartition(PUNICODE_STRING SystemRootPath, - PUNICODE_STRING SourceRootPath, - PUNICODE_STRING DestinationArcPath, - UCHAR PartitionType) +InstallVBRToPartition( + PUNICODE_STRING SystemRootPath, + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING DestinationArcPath, + UCHAR PartitionType) { if ((PartitionType == PARTITION_FAT_12) || (PartitionType == PARTITION_FAT_16) || @@ -2245,58 +2193,57 @@ InstallVBRToPartition(PUNICODE_STRING SystemRootPath, NTSTATUS -InstallFatBootcodeToFloppy(PUNICODE_STRING SourceRootPath, - PUNICODE_STRING DestinationArcPath) +InstallFatBootcodeToFloppy( + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING DestinationArcPath) { #ifdef __REACTOS__ - WCHAR SrcPath[MAX_PATH]; - WCHAR DstPath[MAX_PATH]; - NTSTATUS Status; + WCHAR SrcPath[MAX_PATH]; + WCHAR DstPath[MAX_PATH]; + NTSTATUS Status; - /* Copy FreeLoader to the boot partition */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\freeldr.sys"); + /* Copy FreeLoader to the boot partition */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\freeldr.sys"); - wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys"); + wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys"); - DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); - Status = SetupCopyFile(SrcPath, DstPath); - if (!NT_SUCCESS(Status)) + DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); + Status = SetupCopyFile(SrcPath, DstPath); + if (!NT_SUCCESS(Status)) { - DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); - return Status; + DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status); + return Status; } - /* Create new 'freeldr.ini' */ - wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini"); + /* Create new 'freeldr.ini' */ + wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini"); - DPRINT("Create new 'freeldr.ini'\n"); - Status = CreateFreeLoaderIniForReactos(DstPath, - DestinationArcPath->Buffer); - if (!NT_SUCCESS(Status)) + DPRINT("Create new 'freeldr.ini'\n"); + Status = CreateFreeLoaderIniForReactos(DstPath, DestinationArcPath->Buffer); + if (!NT_SUCCESS(Status)) { - DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status); - return Status; + DPRINT1("CreateFreeLoaderIniForReactos() failed (Status %lx)\n", Status); + return Status; } - /* Install FAT12/16 boosector */ - wcscpy(SrcPath, SourceRootPath->Buffer); - wcscat(SrcPath, L"\\loader\\fat.bin"); + /* Install FAT12/16 boosector */ + wcscpy(SrcPath, SourceRootPath->Buffer); + wcscat(SrcPath, L"\\loader\\fat.bin"); - wcscpy(DstPath, L"\\Device\\Floppy0"); + wcscpy(DstPath, L"\\Device\\Floppy0"); - DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); - Status = InstallFat16BootCodeToDisk(SrcPath, - DstPath); - if (!NT_SUCCESS(Status)) + DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); + Status = InstallFat16BootCodeToDisk(SrcPath, DstPath); + if (!NT_SUCCESS(Status)) { - DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); - return Status; + DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status); + return Status; } - return STATUS_SUCCESS; + return STATUS_SUCCESS; #else - return STATUS_NOT_IMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; #endif } diff --git a/base/shell/cmd/assoc.c b/base/shell/cmd/assoc.c index e5c931e4e88..4abbd672119 100644 --- a/base/shell/cmd/assoc.c +++ b/base/shell/cmd/assoc.c @@ -18,7 +18,6 @@ */ #include -#include #ifdef INCLUDE_CMD_ASSOC diff --git a/base/system/services/database.c b/base/system/services/database.c index 0d7ec77e152..1c5dd29fa55 100644 --- a/base/system/services/database.c +++ b/base/system/services/database.c @@ -25,6 +25,7 @@ /* GLOBALS *******************************************************************/ +LIST_ENTRY ImageListHead; LIST_ENTRY ServiceListHead; static RTL_RESOURCE DatabaseLock; @@ -34,6 +35,232 @@ static CRITICAL_SECTION ControlServiceCriticalSection; /* FUNCTIONS *****************************************************************/ +static DWORD +ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage) +{ + WCHAR szControlPipeName[MAX_PATH + 1]; + HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE; + DWORD ServiceCurrent = 0; + DWORD KeyDisposition; + DWORD dwKeySize; + DWORD dwError; + + /* Get the service number */ + /* TODO: Create registry entry with correct write access */ + dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL, + REG_OPTION_VOLATILE, + KEY_WRITE | KEY_READ, + NULL, + &hServiceCurrentKey, + &KeyDisposition); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError); + return dwError; + } + + if (KeyDisposition == REG_OPENED_EXISTING_KEY) + { + dwKeySize = sizeof(DWORD); + dwError = RegQueryValueExW(hServiceCurrentKey, + L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize); + + if (dwError != ERROR_SUCCESS) + { + RegCloseKey(hServiceCurrentKey); + DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError); + return dwError; + } + + ServiceCurrent++; + } + + dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent)); + + RegCloseKey(hServiceCurrentKey); + + if (dwError != ERROR_SUCCESS) + { + DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError); + return dwError; + } + + /* Create '\\.\pipe\net\NtControlPipeXXX' instance */ + swprintf(szControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent); + + DPRINT("PipeName: %S\n", szControlPipeName); + + pServiceImage->hControlPipe = CreateNamedPipeW(szControlPipeName, + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 100, + 8000, + 4, + 30000, + NULL); + DPRINT("CreateNamedPipeW(%S) done\n", szControlPipeName); + if (pServiceImage->hControlPipe == INVALID_HANDLE_VALUE) + { + DPRINT1("Failed to create control pipe!\n"); + return GetLastError(); + } + + return ERROR_SUCCESS; +} + + +static PSERVICE_IMAGE +ScmGetServiceImageByImagePath(LPWSTR lpImagePath) +{ + PLIST_ENTRY ImageEntry; + PSERVICE_IMAGE CurrentImage; + + DPRINT("ScmGetServiceImageByImagePath(%S) called\n", lpImagePath); + + ImageEntry = ImageListHead.Flink; + while (ImageEntry != &ImageListHead) + { + CurrentImage = CONTAINING_RECORD(ImageEntry, + SERVICE_IMAGE, + ImageListEntry); + if (_wcsicmp(CurrentImage->szImagePath, lpImagePath) == 0) + { + DPRINT("Found image: '%S'\n", CurrentImage->szImagePath); + return CurrentImage; + } + + ImageEntry = ImageEntry->Flink; + } + + DPRINT1("Couldn't find a matching image\n"); + + return NULL; + +} + + +static DWORD +ScmCreateOrReferenceServiceImage(PSERVICE pService) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + UNICODE_STRING ImagePath; + PSERVICE_IMAGE pServiceImage = NULL; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + + DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService); + + RtlInitUnicodeString(&ImagePath, NULL); + + /* Get service data */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"ImagePath"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &ImagePath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + pService->lpServiceName, + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + return RtlNtStatusToDosError(Status); + } + + DPRINT("ImagePath: '%wZ'\n", &ImagePath); + + pServiceImage = ScmGetServiceImageByImagePath(ImagePath.Buffer); + if (pServiceImage == NULL) + { + /* Create a new service image */ + pServiceImage = (PSERVICE_IMAGE)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(SERVICE_IMAGE) + ((wcslen(ImagePath.Buffer) + 1) * sizeof(WCHAR))); + if (pServiceImage == NULL) + { + dwError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + pServiceImage->dwImageRunCount = 1; + pServiceImage->hControlPipe = INVALID_HANDLE_VALUE; + pServiceImage->hProcess = INVALID_HANDLE_VALUE; + + /* Set the image path */ + wcscpy(pServiceImage->szImagePath, + ImagePath.Buffer); + + RtlFreeUnicodeString(&ImagePath); + + /* Create the control pipe */ + dwError = ScmCreateNewControlPipe(pServiceImage); + if (dwError != ERROR_SUCCESS) + { + HeapFree(GetProcessHeap(), 0, pServiceImage); + goto done; + } + + /* FIXME: Add more initialization code here */ + + + /* Append service record */ + InsertTailList(&ImageListHead, + &pServiceImage->ImageListEntry); + } + else + { + /* Increment the run counter */ + pServiceImage->dwImageRunCount++; + } + + DPRINT("pServiceImage->dwImageRunCount: %lu\n", pServiceImage->dwImageRunCount); + + /* Link the service image to the service */ + pService->lpImage = pServiceImage; + +done:; + RtlFreeUnicodeString(&ImagePath); + + DPRINT("ScmCreateOrReferenceServiceImage() done (Error: %lu)\n", dwError); + + return dwError; +} + + +static VOID +ScmDereferenceServiceImage(PSERVICE_IMAGE pServiceImage) +{ + DPRINT1("ScmDereferenceServiceImage() called\n"); + + pServiceImage->dwImageRunCount--; + + if (pServiceImage->dwImageRunCount == 0) + { + DPRINT1("dwImageRunCount == 0\n"); + + /* FIXME: Terminate the process */ + + /* Remove the service image from the list */ + RemoveEntryList(&pServiceImage->ImageListEntry); + + /* Close the control pipe */ + if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE) + CloseHandle(pServiceImage->hControlPipe); + + /* Close the process handle */ + if (pServiceImage->hProcess != INVALID_HANDLE_VALUE) + CloseHandle(pServiceImage->hProcess); + + /* Release the service image */ + HeapFree(GetProcessHeap(), 0, pServiceImage); + } +} + PSERVICE ScmGetServiceEntryByName(LPCWSTR lpServiceName) @@ -131,7 +358,7 @@ ScmCreateNewServiceRecord(LPCWSTR lpServiceName, DPRINT("Service: '%S'\n", lpServiceName); /* Allocate service entry */ - lpService = (SERVICE*) HeapAlloc(GetProcessHeap(), + lpService = (SERVICE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICE) + ((wcslen(lpServiceName) + 1) * sizeof(WCHAR))); if (lpService == NULL) @@ -173,9 +400,9 @@ ScmDeleteServiceRecord(PSERVICE lpService) lpService->lpDisplayName != lpService->lpServiceName) HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); - /* Decrement the image reference counter */ + /* Dereference the service image */ if (lpService->lpImage) - lpService->lpImage->dwServiceRefCount--; + ScmDereferenceServiceImage(lpService->lpImage); /* Decrement the group reference counter */ if (lpService->lpGroup) @@ -183,9 +410,6 @@ ScmDeleteServiceRecord(PSERVICE lpService) /* FIXME: SecurityDescriptor */ - /* Close the control pipe */ - if (lpService->ControlPipeHandle != INVALID_HANDLE_VALUE) - CloseHandle(lpService->ControlPipeHandle); /* Remove the Service from the List */ RemoveEntryList(&lpService->ServiceListEntry); @@ -330,6 +554,12 @@ done:; if (lpDisplayName != NULL) HeapFree(GetProcessHeap(), 0, lpDisplayName); + if (lpService != NULL) + { + if (lpService->lpImage != NULL) + ScmDereferenceServiceImage(lpService->lpImage); + } + return dwError; } @@ -479,6 +709,7 @@ ScmCreateServiceDatabase(VOID) return dwError; /* Initialize basic variables */ + InitializeListHead(&ImageListHead); InitializeListHead(&ServiceListHead); /* Initialize the database lock */ @@ -711,14 +942,14 @@ ScmControlService(PSERVICE Service, wcscpy(&ControlPacket->szArguments[0], Service->lpServiceName); /* Send the control packet */ - WriteFile(Service->ControlPipeHandle, + WriteFile(Service->lpImage->hControlPipe, ControlPacket, sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)), &dwWriteCount, NULL); /* Read the reply */ - ReadFile(Service->ControlPipeHandle, + ReadFile(Service->lpImage->hControlPipe, &ReplyPacket, sizeof(SCM_REPLY_PACKET), &dwReadCount, @@ -734,6 +965,12 @@ ScmControlService(PSERVICE Service, dwError = ReplyPacket.dwError; } + if (dwError == ERROR_SUCCESS && + dwControl == SERVICE_CONTROL_STOP) + { + ScmDereferenceServiceImage(Service->lpImage); + } + LeaveCriticalSection(&ControlServiceCriticalSection); DPRINT("ScmControlService() done\n"); @@ -804,14 +1041,14 @@ ScmSendStartCommand(PSERVICE Service, *Ptr = 0; /* Send the start command */ - WriteFile(Service->ControlPipeHandle, + WriteFile(Service->lpImage->hControlPipe, ControlPacket, sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR), &dwWriteCount, NULL); /* Read the reply */ - ReadFile(Service->ControlPipeHandle, + ReadFile(Service->lpImage->hControlPipe, &ReplyPacket, sizeof(SCM_REPLY_PACKET), &dwReadCount, @@ -838,106 +1075,19 @@ ScmStartUserModeService(PSERVICE Service, DWORD argc, LPWSTR *argv) { - RTL_QUERY_REGISTRY_TABLE QueryTable[3]; PROCESS_INFORMATION ProcessInformation; STARTUPINFOW StartupInfo; - UNICODE_STRING ImagePath; - ULONG Type; - DWORD ServiceCurrent = 0; BOOL Result; - NTSTATUS Status; DWORD dwError = ERROR_SUCCESS; - WCHAR NtControlPipeName[MAX_PATH + 1]; - HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE; - DWORD KeyDisposition; DWORD dwProcessId; - RtlInitUnicodeString(&ImagePath, NULL); - - /* Get service data */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"Type"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = &Type; - - QueryTable[1].Name = L"ImagePath"; - QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[1].EntryContext = &ImagePath; + DPRINT("ScmStartUserModeService(%p)\n", Service); - Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - Service->lpServiceName, - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - return RtlNtStatusToDosError(Status); - } - DPRINT("ImagePath: '%S'\n", ImagePath.Buffer); - DPRINT("Type: %lx\n", Type); - - /* Get the service number */ - /* TODO: Create registry entry with correct write access */ - Status = RegCreateKeyExW(HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL, - REG_OPTION_VOLATILE, - KEY_WRITE | KEY_READ, - NULL, - &hServiceCurrentKey, - &KeyDisposition); - - if (ERROR_SUCCESS != Status) - { - DPRINT1("RegCreateKeyEx() failed with status %u\n", Status); - return Status; - } - - if (REG_OPENED_EXISTING_KEY == KeyDisposition) - { - DWORD KeySize = sizeof(ServiceCurrent); - Status = RegQueryValueExW(hServiceCurrentKey, L"", 0, NULL, (BYTE*)&ServiceCurrent, &KeySize); - - if (ERROR_SUCCESS != Status) - { - RegCloseKey(hServiceCurrentKey); - DPRINT1("RegQueryValueEx() failed with status %u\n", Status); - return Status; - } - - ServiceCurrent++; - } - - Status = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent)); - - RegCloseKey(hServiceCurrentKey); - - if (ERROR_SUCCESS != Status) + /* If the image is already running ... */ + if (Service->lpImage->dwImageRunCount > 1) { - DPRINT1("RegSetValueExW() failed (Status %lx)\n", Status); - return Status; - } - - /* Create '\\.\pipe\net\NtControlPipeXXX' instance */ - swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent); - - DPRINT("Service: %p ImagePath: %wZ PipeName: %S\n", Service, &ImagePath, NtControlPipeName); - - Service->ControlPipeHandle = CreateNamedPipeW(NtControlPipeName, - PIPE_ACCESS_DUPLEX, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, - 100, - 8000, - 4, - 30000, - NULL); - DPRINT("CreateNamedPipeW(%S) done\n", NtControlPipeName); - if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE) - { - DPRINT1("Failed to create control pipe!\n"); - return GetLastError(); + /* ... just send a start command */ + return ScmSendStartCommand(Service, argc, argv); } StartupInfo.cb = sizeof(StartupInfo); @@ -949,7 +1099,7 @@ ScmStartUserModeService(PSERVICE Service, StartupInfo.lpReserved2 = 0; Result = CreateProcessW(NULL, - ImagePath.Buffer, + Service->lpImage->szImagePath, NULL, NULL, FALSE, @@ -958,15 +1108,9 @@ ScmStartUserModeService(PSERVICE Service, NULL, &StartupInfo, &ProcessInformation); - RtlFreeUnicodeString(&ImagePath); - if (!Result) { dwError = GetLastError(); - /* Close control pipe */ - CloseHandle(Service->ControlPipeHandle); - Service->ControlPipeHandle = INVALID_HANDLE_VALUE; - DPRINT1("Starting '%S' failed!\n", Service->lpServiceName); return dwError; } @@ -978,15 +1122,15 @@ ScmStartUserModeService(PSERVICE Service, ProcessInformation.dwThreadId, ProcessInformation.hThread); - /* Get process and thread ids */ - Service->ProcessId = ProcessInformation.dwProcessId; - Service->ThreadId = ProcessInformation.dwThreadId; + /* Get process handle and id */ + Service->lpImage->dwProcessId = ProcessInformation.dwProcessId; + Service->lpImage->hProcess = ProcessInformation.hProcess; /* Resume Thread */ ResumeThread(ProcessInformation.hThread); /* Connect control pipe */ - if (ConnectNamedPipe(Service->ControlPipeHandle, NULL) ? + if (ConnectNamedPipe(Service->lpImage->hControlPipe, NULL) ? TRUE : (dwError = GetLastError()) == ERROR_PIPE_CONNECTED) { DWORD dwRead = 0; @@ -994,7 +1138,7 @@ ScmStartUserModeService(PSERVICE Service, DPRINT("Control pipe connected!\n"); /* Read SERVICE_STATUS_HANDLE from pipe */ - if (!ReadFile(Service->ControlPipeHandle, + if (!ReadFile(Service->lpImage->hControlPipe, (LPVOID)&dwProcessId, sizeof(DWORD), &dwRead, @@ -1015,17 +1159,10 @@ ScmStartUserModeService(PSERVICE Service, else { DPRINT1("Connecting control pipe failed! (Error %lu)\n", dwError); - - /* Close control pipe */ - CloseHandle(Service->ControlPipeHandle); - Service->ControlPipeHandle = INVALID_HANDLE_VALUE; - Service->ProcessId = 0; - Service->ThreadId = 0; } - /* Close process and thread handle */ + /* Close thread handle */ CloseHandle(ProcessInformation.hThread); - CloseHandle(ProcessInformation.hProcess); return dwError; } @@ -1051,7 +1188,6 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv) return ERROR_SERVICE_ALREADY_RUNNING; } - Service->ControlPipeHandle = INVALID_HANDLE_VALUE; DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType); if (Service->Status.dwServiceType & SERVICE_DRIVER) @@ -1067,14 +1203,23 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv) else { /* Start user-mode service */ - dwError = ScmStartUserModeService(Service, argc, argv); + dwError = ScmCreateOrReferenceServiceImage(Service); if (dwError == ERROR_SUCCESS) { + dwError = ScmStartUserModeService(Service, argc, argv); + if (dwError == ERROR_SUCCESS) + { #ifdef USE_SERVICE_START_PENDING - Service->Status.dwCurrentState = SERVICE_START_PENDING; + Service->Status.dwCurrentState = SERVICE_START_PENDING; #else - Service->Status.dwCurrentState = SERVICE_RUNNING; + Service->Status.dwCurrentState = SERVICE_RUNNING; #endif + } + else + { + ScmDereferenceServiceImage(Service->lpImage); + Service->lpImage = NULL; + } } } diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c index 58d8b5d3452..4e455b812b6 100644 --- a/base/system/services/rpcserver.c +++ b/base/system/services/rpcserver.c @@ -586,7 +586,7 @@ DWORD RControlService( lpService = hSvc->ServiceEntry; if (lpService == NULL) { - DPRINT1("lpService == NULL!\n"); + DPRINT1("lpService == NULL!\n"); return ERROR_INVALID_HANDLE; } @@ -723,15 +723,6 @@ DWORD RControlService( if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded)) dwError = ERROR_DEPENDENT_SERVICES_RUNNING; - if (dwError == ERROR_SUCCESS && - dwControl == SERVICE_CONTROL_STOP && - lpServiceStatus->dwCurrentState == SERVICE_STOPPED) - { - lpService->ProcessId = 0; /* FIXME */ - lpService->ThreadId = 0; - } - - return dwError; } @@ -982,7 +973,7 @@ DWORD RSetServiceObjectSecurity( TRUE, &hToken); if (!NT_SUCCESS(Status)) - return RtlNtStatusToDosError(Status); + return RtlNtStatusToDosError(Status); RpcRevertToSelf(); @@ -1611,7 +1602,7 @@ ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName) } /* Do a real query now */ - LinkTarget.Length = BufferSize; + LinkTarget.Length = (USHORT)BufferSize; LinkTarget.MaximumLength = LinkTarget.Length + sizeof(WCHAR); Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize); @@ -2500,7 +2491,7 @@ DWORD REnumServicesStatusW( dwRequiredSize += dwSize; } - if (dwError == 0) + if (dwError == 0) { *pcbBytesNeeded = 0; if (lpResumeHandle) *lpResumeHandle = 0; @@ -3714,7 +3705,7 @@ DWORD REnumServicesStatusA( lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer; lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA)); - lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + + lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW)); for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) @@ -4795,7 +4786,7 @@ DWORD RQueryServiceConfig2W( goto done; } - lpFailureActions->cActions = 0; + lpFailureActions->cActions = 0; lpFailureActions->dwResetPeriod = 0; lpFailureActions->lpCommand = NULL; lpFailureActions->lpRebootMsg = NULL; @@ -4897,7 +4888,7 @@ DWORD RQueryServiceStatusEx( &lpService->Status, sizeof(SERVICE_STATUS)); - lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */ + lpStatus->dwProcessId = (lpService->lpImage != NULL) ? lpService->lpImage->dwProcessId : 0; /* FIXME */ lpStatus->dwServiceFlags = 0; /* FIXME */ /* Unlock the service database */ @@ -4975,7 +4966,7 @@ DWORD REnumServicesStatusExA( lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer; lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA)); - lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + + lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) @@ -5282,7 +5273,8 @@ DWORD REnumServicesStatusExW( memcpy(&lpStatusPtr->ServiceStatusProcess, &CurrentService->Status, sizeof(SERVICE_STATUS)); - lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */ + lpStatusPtr->ServiceStatusProcess.dwProcessId = + (CurrentService->lpImage != NULL) ? CurrentService->lpImage->dwProcessId : 0; /* FIXME */ lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ lpStatusPtr++; @@ -5294,7 +5286,7 @@ DWORD REnumServicesStatusExW( } } - if (dwError == 0) + if (dwError == 0) { *pcbBytesNeeded = 0; if (lpResumeIndex) diff --git a/base/system/services/services.h b/base/system/services/services.h index f080af63bd9..dc9c6098da6 100644 --- a/base/system/services/services.h +++ b/base/system/services/services.h @@ -27,8 +27,14 @@ typedef struct _SERVICE_GROUP typedef struct _SERVICE_IMAGE { - DWORD dwServiceRefCount; // Number of running services of this image - DWORD Dummy; + LIST_ENTRY ImageListEntry; + DWORD dwImageRunCount; + + HANDLE hControlPipe; + HANDLE hProcess; + DWORD dwProcessId; + + WCHAR szImagePath[1]; } SERVICE_IMAGE, *PSERVICE_IMAGE; @@ -54,10 +60,6 @@ typedef struct _SERVICE BOOLEAN ServiceVisited; - HANDLE ControlPipeHandle; - ULONG ProcessId; - ULONG ThreadId; - WCHAR szServiceName[1]; } SERVICE, *PSERVICE; @@ -66,6 +68,7 @@ typedef struct _SERVICE extern LIST_ENTRY ServiceListHead; extern LIST_ENTRY GroupListHead; +extern LIST_ENTRY ImageListHead; extern BOOL ScmShutdown; diff --git a/boot/bootdata/hivesys_amd64.inf b/boot/bootdata/hivesys_amd64.inf index 29619b41e70..e3f8a5c5e42 100644 --- a/boot/bootdata/hivesys_amd64.inf +++ b/boot/bootdata/hivesys_amd64.inf @@ -619,68 +619,68 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE1 HKLM,"SYSTEM\CurrentControlSet\Control\NetworkProvider\Order","ProviderOrder",0x00000000,"" ; NLS Files -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","37",0x00000000,"c_037.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","424",0x00000000,"c_424.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","437",0x00000000,"c_437.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","500",0x00000000,"c_500.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","737",0x00000000,"c_737.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","775",0x00000000,"c_775.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","850",0x00000000,"c_850.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","852",0x00000000,"c_852.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","855",0x00000000,"c_855.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","856",0x00000000,"c_856.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","857",0x00000000,"c_857.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","860",0x00000000,"c_860.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","861",0x00000000,"c_861.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","862",0x00000000,"c_862.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","863",0x00000000,"c_863.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","864",0x00000000,"c_864.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","865",0x00000000,"c_865.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","866",0x00000000,"c_866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","869",0x00000000,"c_869.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","874",0x00000000,"c_874.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","875",0x00000000,"c_875.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","878",0x00000000,"c_878.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","932",0x00000000,"c_932.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","936",0x00000000,"c_936.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","949",0x00000000,"c_949.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","950",0x00000000,"c_950.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1006",0x00000000,"c_1006.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1026",0x00000000,"c_1026.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1250",0x00000000,"c_1250.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1251",0x00000000,"c_1251.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1252",0x00000000,"c_1252.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1253",0x00000000,"c_1253.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1254",0x00000000,"c_1254.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1255",0x00000000,"c_1255.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1256",0x00000000,"c_1256.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1257",0x00000000,"c_1257.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1258",0x00000000,"c_1258.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10000",0x00000000,"c_10000.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10006",0x00000000,"c_10006.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10007",0x00000000,"c_10007.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10029",0x00000000,"c_10029.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10079",0x00000000,"c_10079.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10081",0x00000000,"c_10081.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","20866",0x00000000,"c_20866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","21866",0x00000000,"c_21866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28591",0x00000000,"c_28591.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28592",0x00000000,"c_28592.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28593",0x00000000,"c_28593.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28594",0x00000000,"c_28594.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28595",0x00000000,"c_28595.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28596",0x00000000,"c_28596.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28597",0x00000000,"c_28597.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28598",0x00000000,"c_28598.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28599",0x00000000,"c_28599.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28600",0x00000000,"c_28600.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28603",0x00000000,"c_28603.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28604",0x00000000,"c_28604.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28605",0x00000000,"c_28605.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28606",0x00000000,"c_28606.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","ACP",0x00000000,"1252" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","OEMCP",0x00000000,"437" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","MACCP",0x00000000,"10000" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","37",0x00000000,"c_037.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","424",0x00000000,"c_424.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","437",0x00000000,"c_437.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","500",0x00000000,"c_500.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","737",0x00000000,"c_737.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","775",0x00000000,"c_775.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","850",0x00000000,"c_850.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","852",0x00000000,"c_852.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","855",0x00000000,"c_855.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","856",0x00000000,"c_856.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","857",0x00000000,"c_857.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","860",0x00000000,"c_860.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","861",0x00000000,"c_861.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","862",0x00000000,"c_862.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","863",0x00000000,"c_863.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","864",0x00000000,"c_864.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","865",0x00000000,"c_865.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","866",0x00000000,"c_866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","869",0x00000000,"c_869.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","874",0x00000000,"c_874.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","875",0x00000000,"c_875.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","878",0x00000000,"c_878.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","932",0x00000000,"c_932.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","936",0x00000000,"c_936.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","949",0x00000000,"c_949.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","950",0x00000000,"c_950.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1006",0x00000000,"c_1006.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1026",0x00000000,"c_1026.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1250",0x00000000,"c_1250.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1251",0x00000000,"c_1251.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1252",0x00000000,"c_1252.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1253",0x00000000,"c_1253.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1254",0x00000000,"c_1254.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1255",0x00000000,"c_1255.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1256",0x00000000,"c_1256.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1257",0x00000000,"c_1257.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1258",0x00000000,"c_1258.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10000",0x00000000,"c_10000.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10006",0x00000000,"c_10006.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10007",0x00000000,"c_10007.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10029",0x00000000,"c_10029.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10079",0x00000000,"c_10079.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10081",0x00000000,"c_10081.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","20866",0x00000000,"c_20866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","21866",0x00000000,"c_21866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28591",0x00000000,"c_28591.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28592",0x00000000,"c_28592.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28593",0x00000000,"c_28593.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28594",0x00000000,"c_28594.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28595",0x00000000,"c_28595.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28596",0x00000000,"c_28596.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28597",0x00000000,"c_28597.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28598",0x00000000,"c_28598.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28599",0x00000000,"c_28599.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28600",0x00000000,"c_28600.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28603",0x00000000,"c_28603.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28604",0x00000000,"c_28604.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28605",0x00000000,"c_28605.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28606",0x00000000,"c_28606.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","ACP",0x00000000,"1252" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","OEMCP",0x00000000,"437" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","MACCP",0x00000000,"10000" HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","932",2,"F040-F9FC" HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","936",2,"AAA1-AFFE,F8A1-FEFE,A140-A7A0" @@ -689,253 +689,253 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","950",2,"FA40 HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","Unicode",2,"E000-F8FF" ; NLS Language settings -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0402",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0403",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0404",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0804",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c04",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1004",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1404",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0405",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0406",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0407",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0807",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c07",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1407",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0408",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0809",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c09",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1809",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c09",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100a",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","200a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","240a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","280a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","300a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","340a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","380a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","400a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","440a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","480a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","4c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","500a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040b",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0410",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0810",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0411",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0412",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0413",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0813",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0814",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0415",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0416",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0816",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0417",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0418",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0419",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c1a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041b",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041f",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0420",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0421",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0422",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0423",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0424",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0425",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0426",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0427",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0429",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042b",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042c",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","082c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0436",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0437",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0438",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0439",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","083e",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043f",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0440",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0441",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0443",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0843",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0445",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0455",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0456",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","048f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0490",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","Default",0x00000000,"0409" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","InstallLanguage",0x00000000,"0409" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0402",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0403",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0404",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0804",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c04",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1004",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1404",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0405",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0406",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0407",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0807",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c07",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1407",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0408",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0809",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c09",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1809",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1c09",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","2009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","080a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","100a",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","140a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","180a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","200a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","240a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","280a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","2c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","300a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","340a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","380a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","400a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","440a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","480a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","4c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","500a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040b",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","080c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c0c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","100c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","140c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","180c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0410",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0810",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0411",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0412",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0413",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0414",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0813",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0414",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0814",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0415",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0416",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0816",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0417",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0418",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0419",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","081a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c1a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041b",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","081d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041f",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0420",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0421",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0422",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0423",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0424",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0425",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0426",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0427",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0429",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042b",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042c",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","082c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0436",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0437",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0438",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0439",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","043e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","083e",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","043f",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0440",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0441",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0443",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0843",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0445",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0455",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0456",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","048f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0490",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","Default",0x00000000,"0409" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","InstallLanguage",0x00000000,"0409" ; Supported and installed locales ; If you add/uncomment an entry here, please also add the appropriate Language ; in the previous section. -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000402",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000403",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000404",0x00000000,"9" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000804",0x00000000,"a" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000405",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000406",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000807",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c07",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000408",0x00000000,"4" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000809",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c09",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001809",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c09",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100a",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000200a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000240a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000280a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000300a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000340a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000380a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000400a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000440a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000480a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00004c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000500a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040b",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040d",0x00000000,"c" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040e",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040f",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000410",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000810",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000411",0x00000000,"7" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000412",0x00000000,"8" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000413",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000813",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000414",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000814",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000415",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000416",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000816",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000417",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000418",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000419",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041a",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c1a",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041b",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041c",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041e",0x00000000,"b" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041f",0x00000000,"6" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000420",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000421",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000422",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000423",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000424",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000425",0x00000000,"3" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000426",0x00000000,"3" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000427",0x00000000,"3" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000429",0x00000000,"" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042a",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042b",0x00000000,"11" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042c",0x00000000,"6" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000082c",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042f",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000436",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000437",0x00000000,"10" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000438",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000439",0x00000000,"f" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043e",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000083e",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043f",0x00000000,"5" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000440",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000441",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000443",0x00000000,"6" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000843",0x00000000,"5" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000445",0x00000000,"f" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000455",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000456",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000048f",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000490",0x00000000,"1" - -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","1",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","2",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","3",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","4",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","5",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","6",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","7",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","8",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","9",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","10",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","11",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","b",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","e",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","f",0x00000000,"1" - -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","0001040e",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010437",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00020804",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021004",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021404",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00030404",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale",,0x00000012 +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000402",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000403",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000404",0x00000000,"9" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000804",0x00000000,"a" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000405",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000406",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000807",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c07",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000408",0x00000000,"4" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000809",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c09",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001809",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001c09",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00002009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000080a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000100a",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000140a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000180a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000200a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000240a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000280a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00002c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000300a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000340a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000380a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000400a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000440a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000480a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00004c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000500a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040b",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000080c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c0c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000100c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000140c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000180c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040d",0x00000000,"c" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040e",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040f",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000410",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000810",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000411",0x00000000,"7" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000412",0x00000000,"8" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000413",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000813",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000414",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000814",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000415",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000416",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000816",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000417",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000418",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000419",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041a",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000081a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c1a",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041b",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041c",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000081d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041e",0x00000000,"b" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041f",0x00000000,"6" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000420",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000421",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000422",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000423",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000424",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000425",0x00000000,"3" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000426",0x00000000,"3" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000427",0x00000000,"3" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000429",0x00000000,"" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042a",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042b",0x00000000,"11" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042c",0x00000000,"6" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000082c",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042f",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000436",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000437",0x00000000,"10" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000438",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000439",0x00000000,"f" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000043e",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000083e",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000043f",0x00000000,"5" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000440",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000441",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000443",0x00000000,"6" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000843",0x00000000,"5" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000445",0x00000000,"f" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000455",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000456",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000048f",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000490",0x00000000,"1" + +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","1",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","2",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","3",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","4",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","5",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","6",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","7",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","8",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","9",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","10",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","11",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","b",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","e",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","f",0x00000000,"1" + +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00010407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","0001040e",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00010437",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00020804",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00021004",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00021404",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00030404",0x00000000,"" HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82441FX",0x00030003,\ 01,00,00,00,86,80,37,12,00,00,00,00,00,00,00,00 @@ -1348,9 +1348,9 @@ HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","ImagePath",0x00020000,"%System HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Start",0x00010001,0x00000003 HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Type",0x00010001,0x00000020 -; ReactOS Telnet Daemon -HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Description",0x00000000,"ReactOS Telnet Daemon" -HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","DisplayName",0x00000000,"ReactOS Telnet Daemon" +; ReactOS Telnet Service +HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Description",0x00000000,"ReactOS Telnet Service" +HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","DisplayName",0x00000000,"ReactOS Telnet Service" HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ErrorControl",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Group",0x00000000,"Network" HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ImagePath",0x00020000,"%SystemRoot%\system32\telnetd.exe" diff --git a/boot/bootdata/hivesys_arm.inf b/boot/bootdata/hivesys_arm.inf index e766a5aaad5..2fac7e7ef79 100644 --- a/boot/bootdata/hivesys_arm.inf +++ b/boot/bootdata/hivesys_arm.inf @@ -381,317 +381,317 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE1 HKLM,"SYSTEM\CurrentControlSet\Control\NetworkProvider\Order","ProviderOrder",0x00000000,"" ; NLS Files -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","37",0x00000000,"c_037.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","424",0x00000000,"c_424.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","437",0x00000000,"c_437.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","500",0x00000000,"c_500.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","737",0x00000000,"c_737.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","775",0x00000000,"c_775.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","850",0x00000000,"c_850.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","852",0x00000000,"c_852.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","855",0x00000000,"c_855.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","856",0x00000000,"c_856.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","857",0x00000000,"c_857.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","860",0x00000000,"c_860.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","861",0x00000000,"c_861.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","862",0x00000000,"c_862.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","863",0x00000000,"c_863.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","864",0x00000000,"c_864.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","865",0x00000000,"c_865.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","866",0x00000000,"c_866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","869",0x00000000,"c_869.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","874",0x00000000,"c_874.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","875",0x00000000,"c_875.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","878",0x00000000,"c_878.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","932",0x00000000,"c_932.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","936",0x00000000,"c_936.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","949",0x00000000,"c_949.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","950",0x00000000,"c_950.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1006",0x00000000,"c_1006.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1026",0x00000000,"c_1026.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1250",0x00000000,"c_1250.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1251",0x00000000,"c_1251.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1252",0x00000000,"c_1252.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1253",0x00000000,"c_1253.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1254",0x00000000,"c_1254.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1255",0x00000000,"c_1255.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1256",0x00000000,"c_1256.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1257",0x00000000,"c_1257.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1258",0x00000000,"c_1258.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10000",0x00000000,"c_10000.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10006",0x00000000,"c_10006.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10007",0x00000000,"c_10007.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10029",0x00000000,"c_10029.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10079",0x00000000,"c_10079.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10081",0x00000000,"c_10081.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","20866",0x00000000,"c_20866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","21866",0x00000000,"c_21866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28591",0x00000000,"c_28591.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28592",0x00000000,"c_28592.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28593",0x00000000,"c_28593.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28594",0x00000000,"c_28594.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28595",0x00000000,"c_28595.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28596",0x00000000,"c_28596.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28597",0x00000000,"c_28597.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28598",0x00000000,"c_28598.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28599",0x00000000,"c_28599.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28600",0x00000000,"c_28600.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28603",0x00000000,"c_28603.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28604",0x00000000,"c_28604.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28605",0x00000000,"c_28605.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28606",0x00000000,"c_28606.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","ACP",0x00000000,"1252" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","OEMCP",0x00000000,"437" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","MACCP",0x00000000,"10000" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","37",0x00000000,"c_037.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","424",0x00000000,"c_424.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","437",0x00000000,"c_437.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","500",0x00000000,"c_500.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","737",0x00000000,"c_737.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","775",0x00000000,"c_775.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","850",0x00000000,"c_850.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","852",0x00000000,"c_852.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","855",0x00000000,"c_855.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","856",0x00000000,"c_856.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","857",0x00000000,"c_857.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","860",0x00000000,"c_860.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","861",0x00000000,"c_861.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","862",0x00000000,"c_862.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","863",0x00000000,"c_863.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","864",0x00000000,"c_864.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","865",0x00000000,"c_865.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","866",0x00000000,"c_866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","869",0x00000000,"c_869.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","874",0x00000000,"c_874.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","875",0x00000000,"c_875.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","878",0x00000000,"c_878.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","932",0x00000000,"c_932.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","936",0x00000000,"c_936.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","949",0x00000000,"c_949.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","950",0x00000000,"c_950.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1006",0x00000000,"c_1006.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1026",0x00000000,"c_1026.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1250",0x00000000,"c_1250.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1251",0x00000000,"c_1251.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1252",0x00000000,"c_1252.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1253",0x00000000,"c_1253.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1254",0x00000000,"c_1254.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1255",0x00000000,"c_1255.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1256",0x00000000,"c_1256.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1257",0x00000000,"c_1257.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1258",0x00000000,"c_1258.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10000",0x00000000,"c_10000.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10006",0x00000000,"c_10006.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10007",0x00000000,"c_10007.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10029",0x00000000,"c_10029.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10079",0x00000000,"c_10079.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10081",0x00000000,"c_10081.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","20866",0x00000000,"c_20866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","21866",0x00000000,"c_21866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28591",0x00000000,"c_28591.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28592",0x00000000,"c_28592.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28593",0x00000000,"c_28593.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28594",0x00000000,"c_28594.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28595",0x00000000,"c_28595.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28596",0x00000000,"c_28596.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28597",0x00000000,"c_28597.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28598",0x00000000,"c_28598.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28599",0x00000000,"c_28599.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28600",0x00000000,"c_28600.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28603",0x00000000,"c_28603.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28604",0x00000000,"c_28604.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28605",0x00000000,"c_28605.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28606",0x00000000,"c_28606.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","ACP",0x00000000,"1252" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","OEMCP",0x00000000,"437" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","MACCP",0x00000000,"10000" ; NLS Language settings -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0402",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0403",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0404",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0804",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c04",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1004",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1404",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0405",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0406",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0407",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0807",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c07",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1407",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0408",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0809",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c09",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1809",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c09",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100a",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","200a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","240a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","280a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","300a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","340a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","380a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","400a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","440a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","480a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","4c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","500a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040b",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0410",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0810",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0411",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0412",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0413",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0813",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0814",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0415",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0416",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0816",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0417",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0418",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0419",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c1a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041b",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041f",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0420",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0421",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0422",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0423",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0424",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0425",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0426",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0427",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0429",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042b",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042c",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","082c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0436",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0437",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0438",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0439",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","083e",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043f",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0440",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0441",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0443",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0843",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0445",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0455",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0456",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","048f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0490",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","Default",0x00000000,"0409" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","InstallLanguage",0x00000000,"0409" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0402",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0403",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0404",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0804",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c04",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1004",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1404",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0405",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0406",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0407",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0807",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c07",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1407",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0408",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0809",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c09",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1809",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1c09",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","2009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","080a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","100a",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","140a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","180a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","200a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","240a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","280a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","2c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","300a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","340a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","380a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","400a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","440a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","480a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","4c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","500a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040b",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","080c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c0c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","100c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","140c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","180c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0410",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0810",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0411",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0412",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0413",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0414",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0813",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0414",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0814",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0415",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0416",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0816",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0417",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0418",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0419",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","081a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c1a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041b",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","081d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041f",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0420",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0421",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0422",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0423",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0424",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0425",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0426",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0427",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0429",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042b",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042c",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","082c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0436",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0437",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0438",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0439",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","043e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","083e",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","043f",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0440",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0441",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0443",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0843",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0445",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0455",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0456",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","048f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0490",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","Default",0x00000000,"0409" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","InstallLanguage",0x00000000,"0409" ; Supported and installed locales ; If you add/uncomment an entry here, please also add the appropriate Language ; in the previous section. -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000402",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000403",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000404",0x00000000,"9" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000804",0x00000000,"a" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000405",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000406",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000807",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c07",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000408",0x00000000,"4" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000809",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c09",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001809",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c09",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100a",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000200a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000240a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000280a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000300a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000340a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000380a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000400a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000440a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000480a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00004c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000500a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040b",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040d",0x00000000,"c" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040e",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040f",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000410",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000810",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000411",0x00000000,"7" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000412",0x00000000,"8" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000413",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000813",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000414",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000814",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000415",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000416",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000816",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000417",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000418",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000419",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041a",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c1a",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041b",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041c",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041e",0x00000000,"b" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041f",0x00000000,"6" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000420",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000421",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000422",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000423",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000424",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000425",0x00000000,"3" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000426",0x00000000,"3" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000427",0x00000000,"3" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000429",0x00000000,"" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042a",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042b",0x00000000,"11" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042c",0x00000000,"6" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000082c",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042f",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000436",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000437",0x00000000,"10" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000438",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000439",0x00000000,"f" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043e",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000083e",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043f",0x00000000,"5" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000440",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000441",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000443",0x00000000,"6" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000843",0x00000000,"5" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000445",0x00000000,"f" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000455",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000456",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000048f",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000490",0x00000000,"1" - -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","1",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","2",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","3",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","4",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","5",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","6",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","7",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","8",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","9",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","10",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","11",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","b",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","e",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","f",0x00000000,"1" - -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","0001040e",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010437",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00020804",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021004",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021404",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00030404",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale",,0x00000012 +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000402",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000403",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000404",0x00000000,"9" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000804",0x00000000,"a" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000405",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000406",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000807",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c07",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000408",0x00000000,"4" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000809",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c09",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001809",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001c09",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00002009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000080a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000100a",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000140a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000180a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000200a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000240a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000280a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00002c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000300a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000340a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000380a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000400a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000440a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000480a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00004c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000500a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040b",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000080c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c0c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000100c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000140c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000180c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040d",0x00000000,"c" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040e",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040f",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000410",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000810",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000411",0x00000000,"7" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000412",0x00000000,"8" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000413",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000813",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000414",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000814",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000415",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000416",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000816",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000417",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000418",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000419",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041a",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000081a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c1a",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041b",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041c",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000081d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041e",0x00000000,"b" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041f",0x00000000,"6" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000420",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000421",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000422",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000423",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000424",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000425",0x00000000,"3" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000426",0x00000000,"3" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000427",0x00000000,"3" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000429",0x00000000,"" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042a",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042b",0x00000000,"11" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042c",0x00000000,"6" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000082c",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042f",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000436",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000437",0x00000000,"10" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000438",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000439",0x00000000,"f" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000043e",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000083e",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000043f",0x00000000,"5" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000440",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000441",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000443",0x00000000,"6" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000843",0x00000000,"5" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000445",0x00000000,"f" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000455",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000456",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000048f",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000490",0x00000000,"1" + +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","1",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","2",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","3",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","4",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","5",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","6",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","7",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","8",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","9",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","10",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","11",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","b",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","e",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","f",0x00000000,"1" + +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00010407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","0001040e",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00010437",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00020804",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00021004",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00021404",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00030404",0x00000000,"" ; Some installers check for SP6 HKLM,"SYSTEM\CurrentControlSet\Control\Windows","CSDVersion",0x00010001,0x00000600 diff --git a/boot/bootdata/hivesys_i386.inf b/boot/bootdata/hivesys_i386.inf index c660876dcde..42c7a93ee4b 100644 --- a/boot/bootdata/hivesys_i386.inf +++ b/boot/bootdata/hivesys_i386.inf @@ -712,68 +712,68 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE1 HKLM,"SYSTEM\CurrentControlSet\Control\NetworkProvider\Order","ProviderOrder",0x00000000,"" ; NLS Files -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","37",0x00000000,"c_037.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","424",0x00000000,"c_424.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","437",0x00000000,"c_437.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","500",0x00000000,"c_500.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","737",0x00000000,"c_737.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","775",0x00000000,"c_775.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","850",0x00000000,"c_850.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","852",0x00000000,"c_852.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","855",0x00000000,"c_855.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","856",0x00000000,"c_856.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","857",0x00000000,"c_857.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","860",0x00000000,"c_860.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","861",0x00000000,"c_861.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","862",0x00000000,"c_862.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","863",0x00000000,"c_863.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","864",0x00000000,"c_864.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","865",0x00000000,"c_865.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","866",0x00000000,"c_866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","869",0x00000000,"c_869.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","874",0x00000000,"c_874.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","875",0x00000000,"c_875.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","878",0x00000000,"c_878.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","932",0x00000000,"c_932.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","936",0x00000000,"c_936.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","949",0x00000000,"c_949.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","950",0x00000000,"c_950.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1006",0x00000000,"c_1006.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1026",0x00000000,"c_1026.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1250",0x00000000,"c_1250.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1251",0x00000000,"c_1251.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1252",0x00000000,"c_1252.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1253",0x00000000,"c_1253.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1254",0x00000000,"c_1254.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1255",0x00000000,"c_1255.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1256",0x00000000,"c_1256.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1257",0x00000000,"c_1257.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","1258",0x00000000,"c_1258.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10000",0x00000000,"c_10000.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10006",0x00000000,"c_10006.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10007",0x00000000,"c_10007.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10029",0x00000000,"c_10029.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10079",0x00000000,"c_10079.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","10081",0x00000000,"c_10081.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","20866",0x00000000,"c_20866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","21866",0x00000000,"c_21866.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28591",0x00000000,"c_28591.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28592",0x00000000,"c_28592.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28593",0x00000000,"c_28593.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28594",0x00000000,"c_28594.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28595",0x00000000,"c_28595.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28596",0x00000000,"c_28596.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28597",0x00000000,"c_28597.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28598",0x00000000,"c_28598.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28599",0x00000000,"c_28599.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28600",0x00000000,"c_28600.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28603",0x00000000,"c_28603.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28604",0x00000000,"c_28604.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28605",0x00000000,"c_28605.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","28606",0x00000000,"c_28606.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","ACP",0x00000000,"1252" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","OEMCP",0x00000000,"437" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\CodePage","MACCP",0x00000000,"10000" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","37",0x00000000,"c_037.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","424",0x00000000,"c_424.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","437",0x00000000,"c_437.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","500",0x00000000,"c_500.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","737",0x00000000,"c_737.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","775",0x00000000,"c_775.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","850",0x00000000,"c_850.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","852",0x00000000,"c_852.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","855",0x00000000,"c_855.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","856",0x00000000,"c_856.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","857",0x00000000,"c_857.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","860",0x00000000,"c_860.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","861",0x00000000,"c_861.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","862",0x00000000,"c_862.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","863",0x00000000,"c_863.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","864",0x00000000,"c_864.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","865",0x00000000,"c_865.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","866",0x00000000,"c_866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","869",0x00000000,"c_869.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","874",0x00000000,"c_874.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","875",0x00000000,"c_875.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","878",0x00000000,"c_878.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","932",0x00000000,"c_932.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","936",0x00000000,"c_936.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","949",0x00000000,"c_949.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","950",0x00000000,"c_950.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1006",0x00000000,"c_1006.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1026",0x00000000,"c_1026.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1250",0x00000000,"c_1250.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1251",0x00000000,"c_1251.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1252",0x00000000,"c_1252.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1253",0x00000000,"c_1253.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1254",0x00000000,"c_1254.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1255",0x00000000,"c_1255.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1256",0x00000000,"c_1256.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1257",0x00000000,"c_1257.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","1258",0x00000000,"c_1258.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10000",0x00000000,"c_10000.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10006",0x00000000,"c_10006.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10007",0x00000000,"c_10007.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10029",0x00000000,"c_10029.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10079",0x00000000,"c_10079.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","10081",0x00000000,"c_10081.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","20866",0x00000000,"c_20866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","21866",0x00000000,"c_21866.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28591",0x00000000,"c_28591.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28592",0x00000000,"c_28592.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28593",0x00000000,"c_28593.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28594",0x00000000,"c_28594.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28595",0x00000000,"c_28595.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28596",0x00000000,"c_28596.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28597",0x00000000,"c_28597.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28598",0x00000000,"c_28598.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28599",0x00000000,"c_28599.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28600",0x00000000,"c_28600.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28603",0x00000000,"c_28603.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28604",0x00000000,"c_28604.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28605",0x00000000,"c_28605.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","28606",0x00000000,"c_28606.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","ACP",0x00000000,"1252" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","OEMCP",0x00000000,"437" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage","MACCP",0x00000000,"10000" HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","932",2,"F040-F9FC" HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","936",2,"AAA1-AFFE,F8A1-FEFE,A140-A7A0" @@ -782,253 +782,253 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","950",2,"FA40 HKLM,"SYSTEM\CurrentControlSet\Control\Nls\CodePage\EUDCCodeRange","Unicode",2,"E000-F8FF" ; NLS Language settings -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0402",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0403",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0404",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0804",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c04",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1004",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1404",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0405",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0406",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0407",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0807",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c07",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1407",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0408",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0809",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c09",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1809",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c09",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3009",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3409",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100a",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","1c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","200a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","240a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","280a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","2c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","300a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","340a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","380a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","3c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","400a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","440a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","480a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","4c0a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","500a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040b",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","080c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c0c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","100c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","140c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","180c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","040f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0410",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0810",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0411",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0412",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0413",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0813",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0414",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0814",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0415",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0416",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0816",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0417",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0418",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0419",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0c1a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041b",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","081d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","041f",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0420",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0421",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0422",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0423",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0424",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0425",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0426",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0427",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0429",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042a",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042b",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042c",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","082c",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042d",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","042f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0436",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0437",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0438",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0439",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043e",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","083e",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","043f",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0440",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0441",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0443",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0843",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0445",0x00000000,"l_intl.nls" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0455",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0456",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","048f",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","0490",0x00000000,"l_intl.nls" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","Default",0x00000000,"0409" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language","InstallLanguage",0x00000000,"0409" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0402",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0403",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0404",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0804",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c04",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1004",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1404",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0405",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0406",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0407",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0807",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c07",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1407",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0408",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0809",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c09",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1809",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1c09",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","2009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3009",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3409",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","080a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","100a",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","140a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","180a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","1c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","200a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","240a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","280a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","2c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","300a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","340a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","380a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","3c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","400a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","440a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","480a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","4c0a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","500a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040b",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","080c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c0c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","100c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","140c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","180c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","040f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0410",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0810",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0411",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0412",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0413",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0414",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0813",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0414",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0814",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0415",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0416",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0816",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0417",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0418",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0419",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","081a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0c1a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041b",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","081d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","041f",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0420",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0421",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0422",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0423",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0424",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0425",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0426",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0427",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0429",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042a",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042b",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042c",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","082c",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042d",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","042f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0436",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0437",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0438",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0439",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","043e",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","083e",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","043f",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0440",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0441",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0443",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0843",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0445",0x00000000,"l_intl.nls" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0455",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0456",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","048f",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","0490",0x00000000,"l_intl.nls" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","Default",0x00000000,"0409" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language","InstallLanguage",0x00000000,"0409" ; Supported and installed locales ; If you add/uncomment an entry here, please also add the appropriate Language ; in the previous section. -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000402",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000403",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000404",0x00000000,"9" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000804",0x00000000,"a" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000405",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000406",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000807",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c07",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000408",0x00000000,"4" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000809",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c09",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001809",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c09",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003009",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003409",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100a",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00001c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000200a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000240a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000280a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00002c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000300a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000340a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000380a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00003c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000400a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000440a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000480a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00004c0a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000500a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040b",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000080c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c0c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000100c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000140c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000180c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040d",0x00000000,"c" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040e",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000040f",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000410",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000810",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000411",0x00000000,"7" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000412",0x00000000,"8" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000413",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000813",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000414",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000814",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000415",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000416",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000816",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000417",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000418",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000419",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041a",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000c1a",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041b",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041c",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000081d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041e",0x00000000,"b" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000041f",0x00000000,"6" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000420",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000421",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000422",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000423",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000424",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000425",0x00000000,"3" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000426",0x00000000,"3" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000427",0x00000000,"3" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000429",0x00000000,"" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042a",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042b",0x00000000,"11" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042c",0x00000000,"6" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000082c",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000042f",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000436",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000437",0x00000000,"10" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000438",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000439",0x00000000,"f" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043e",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000083e",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000043f",0x00000000,"5" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000440",0x00000000,"5" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000441",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000443",0x00000000,"6" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000843",0x00000000,"5" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000445",0x00000000,"f" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000455",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000456",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","0000048f",0x00000000,"1" -;HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale","00000490",0x00000000,"1" - -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","1",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","2",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","3",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","4",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","5",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","6",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","7",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","8",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","9",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","10",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","11",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","a",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","b",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","c",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","d",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","e",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Language Groups","f",0x00000000,"1" - -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010407",0x00000000,"1" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","0001040e",0x00000000,"2" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00010437",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00020804",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021004",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00021404",0x00000000,"" -HKLM,"SYSTEM\CurrentControlSet\Control\NLS\Locale\Alternate Sorts","00030404",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale",,0x00000012 +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000402",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000403",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000404",0x00000000,"9" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000804",0x00000000,"a" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000405",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000406",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000807",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c07",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000408",0x00000000,"4" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000809",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c09",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001809",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001c09",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00002009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003009",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003409",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000080a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000100a",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000140a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000180a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00001c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000200a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000240a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000280a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00002c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000300a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000340a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000380a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00003c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000400a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000440a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000480a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00004c0a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000500a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040b",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000080c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c0c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000100c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000140c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000180c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040d",0x00000000,"c" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040e",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000040f",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000410",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000810",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000411",0x00000000,"7" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000412",0x00000000,"8" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000413",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000813",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000414",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000814",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000415",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000416",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000816",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000417",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000418",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000419",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041a",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000081a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000c1a",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041b",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041c",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000081d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041e",0x00000000,"b" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000041f",0x00000000,"6" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000420",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000421",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000422",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000423",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000424",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000425",0x00000000,"3" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000426",0x00000000,"3" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000427",0x00000000,"3" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000429",0x00000000,"" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042a",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042b",0x00000000,"11" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042c",0x00000000,"6" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000082c",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000042f",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000436",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000437",0x00000000,"10" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000438",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000439",0x00000000,"f" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000043e",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000083e",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000043f",0x00000000,"5" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000440",0x00000000,"5" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000441",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000443",0x00000000,"6" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000843",0x00000000,"5" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000445",0x00000000,"f" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000455",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000456",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","0000048f",0x00000000,"1" +;HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale","00000490",0x00000000,"1" + +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","1",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","2",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","3",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","4",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","5",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","6",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","7",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","8",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","9",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","10",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","11",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","a",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","b",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","c",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","d",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","e",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Language Groups","f",0x00000000,"1" + +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00010407",0x00000000,"1" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","0001040e",0x00000000,"2" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00010437",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00020804",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00021004",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00021404",0x00000000,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Nls\Locale\Alternate Sorts","00030404",0x00000000,"" HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Intel 82441FX",0x00030003,\ 01,00,00,00,86,80,37,12,00,00,00,00,00,00,00,00 @@ -1641,9 +1641,9 @@ HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","ObjectName",0x00000000,"LocalS HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Start",0x00010001,0x00000003 HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Type",0x00010001,0x00000020 -; ReactOS Telnet Daemon -HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Description",0x00000000,"ReactOS Telnet Daemon" -HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","DisplayName",0x00000000,"ReactOS Telnet Daemon" +; ReactOS Telnet Service +HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Description",0x00000000,"ReactOS Telnet Service" +HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","DisplayName",0x00000000,"ReactOS Telnet Service" HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ErrorControl",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","Group",0x00000000,"Network" HKLM,"SYSTEM\CurrentControlSet\Services\telnetd","ImagePath",0x00020000,"%SystemRoot%\system32\telnetd.exe" diff --git a/boot/freeldr/bootsect/isoboot.S b/boot/freeldr/bootsect/isoboot.S index 7feb495c179..979c35a1f00 100644 --- a/boot/freeldr/bootsect/isoboot.S +++ b/boot/freeldr/bootsect/isoboot.S @@ -360,10 +360,13 @@ get_fs_structures: call crlf #endif - mov bx, FREELDR_BASE // bx = load address +// use high segment, as some bios can fail, when offset is too big + mov bx, FREELDR_BASE / 16 // es = load segment + mov es, bx + xor ebx, ebx // bx = load offset mov si, di // restore file pointer - mov cx, HEX(0FFFF) // load the whole file - call getfssec // get the whole file + mov cx, HEX(0FFFF) // load the whole file + call getfssec // get the whole file #ifdef DEBUG_MESSAGES mov si, offset startldr_msg diff --git a/boot/freeldr/freeldr/arch/i386/hardware.c b/boot/freeldr/freeldr/arch/i386/hardware.c index 47ec99e6639..87ba7808fa2 100644 --- a/boot/freeldr/freeldr/arch/i386/hardware.c +++ b/boot/freeldr/freeldr/arch/i386/hardware.c @@ -670,7 +670,8 @@ DetectBiosFloppyPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey) if ((FloppyType > 5) || (FloppyType == 0)) continue; - DiskResetController(FloppyNumber); + if (!DiskResetController(FloppyNumber)) + continue; Ptr = GetInt1eTable(); diff --git a/cmake/CMakeDetermineCompilerId.cmake b/cmake/CMakeDetermineCompilerId.cmake new file mode 100644 index 00000000000..b160dee62db --- /dev/null +++ b/cmake/CMakeDetermineCompilerId.cmake @@ -0,0 +1,315 @@ + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# Function to compile a source file to identify the compiler. This is +# used internally by CMake and should not be included by user code. +# If successful, sets CMAKE__COMPILER_ID and CMAKE__PLATFORM_ID + +FUNCTION(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) + # Make sure the compiler arguments are clean. + STRING(STRIP "${CMAKE_${lang}_COMPILER_ARG1}" CMAKE_${lang}_COMPILER_ID_ARG1) + STRING(REGEX REPLACE " +" ";" CMAKE_${lang}_COMPILER_ID_ARG1 "${CMAKE_${lang}_COMPILER_ID_ARG1}") + + # Make sure user-specified compiler flags are used. + IF(CMAKE_${lang}_FLAGS) + SET(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS}) + ELSE(CMAKE_${lang}_FLAGS) + SET(CMAKE_${lang}_COMPILER_ID_FLAGS $ENV{${flagvar}}) + ENDIF(CMAKE_${lang}_FLAGS) + STRING(REGEX REPLACE " " ";" CMAKE_${lang}_COMPILER_ID_FLAGS_LIST "${CMAKE_${lang}_COMPILER_ID_FLAGS}") + + # Compute the directory in which to run the test. + SET(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CompilerId${lang}) + + # Try building with no extra flags and then try each set + # of helper flags. Stop when the compiler is identified. + FOREACH(flags "" ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS}) + IF(NOT CMAKE_${lang}_COMPILER_ID) + CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}") + FOREACH(file ${COMPILER_${lang}_PRODUCED_FILES}) + CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}") + ENDFOREACH(file) + ENDIF(NOT CMAKE_${lang}_COMPILER_ID) + ENDFOREACH(flags) + + # If the compiler is still unknown, try to query its vendor. + IF(NOT CMAKE_${lang}_COMPILER_ID) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang}) + ENDIF() + + # if the format is unknown after all files have been checked, put "Unknown" in the cache + IF(NOT CMAKE_EXECUTABLE_FORMAT) + SET(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format") + ENDIF(NOT CMAKE_EXECUTABLE_FORMAT) + + # Display the final identification result. + IF(CMAKE_${lang}_COMPILER_ID) + MESSAGE(STATUS "The ${lang} compiler identification is " + "${CMAKE_${lang}_COMPILER_ID}") + ELSE(CMAKE_${lang}_COMPILER_ID) + MESSAGE(STATUS "The ${lang} compiler identification is unknown") + ENDIF(CMAKE_${lang}_COMPILER_ID) + + SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE) + SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE) + SET(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}" + PARENT_SCOPE) +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID) + +#----------------------------------------------------------------------------- +# Function to write the compiler id source file. +FUNCTION(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src) + FILE(READ ${CMAKE_ROOT}/Modules/${src}.in ID_CONTENT_IN) + STRING(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY) + FILE(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}") +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_WRITE) + +#----------------------------------------------------------------------------- +# Function to build the compiler id source file and look for output +# files. +FUNCTION(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) + # Create a clean working directory. + FILE(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR}) + FILE(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}) + CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}") + + # Construct a description of this test case. + SET(COMPILER_DESCRIPTION + "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1} +Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} +Id flags: ${testflags} +") + + # Compile the compiler identification source. + IF(COMMAND EXECUTE_PROCESS) + EXECUTE_PROCESS( + COMMAND ${CMAKE_${lang}_COMPILER} + ${CMAKE_${lang}_COMPILER_ID_ARG1} + ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${testflags} + "${src}" + WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR} + OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT + ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT + RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT + ) + ELSE(COMMAND EXECUTE_PROCESS) + EXEC_PROGRAM( + ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_DIR} + ARGS ${CMAKE_${lang}_COMPILER_ID_ARG1} + ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${testflags} + \"${src}\" + OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT + RETURN_VALUE CMAKE_${lang}_COMPILER_ID_RESULT + ) + ENDIF(COMMAND EXECUTE_PROCESS) + + # Check the result of compilation. + IF(CMAKE_${lang}_COMPILER_ID_RESULT) + # Compilation failed. + SET(MSG + "Compiling the ${lang} compiler identification source file \"${src}\" failed. +${COMPILER_DESCRIPTION} +The output was: +${CMAKE_${lang}_COMPILER_ID_RESULT} +${CMAKE_${lang}_COMPILER_ID_OUTPUT} + +") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}") + #IF(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL) + # MESSAGE(FATAL_ERROR "${MSG}") + #ENDIF(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL) + + # No output files should be inspected. + SET(COMPILER_${lang}_PRODUCED_FILES) + ELSE(CMAKE_${lang}_COMPILER_ID_RESULT) + # Compilation succeeded. + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Compiling the ${lang} compiler identification source file \"${src}\" succeeded. +${COMPILER_DESCRIPTION} +The output was: +${CMAKE_${lang}_COMPILER_ID_RESULT} +${CMAKE_${lang}_COMPILER_ID_OUTPUT} + +") + + # Find the executable produced by the compiler, try all files in the + # binary dir. + FILE(GLOB COMPILER_${lang}_PRODUCED_FILES + RELATIVE ${CMAKE_${lang}_COMPILER_ID_DIR} + ${CMAKE_${lang}_COMPILER_ID_DIR}/*) + LIST(REMOVE_ITEM COMPILER_${lang}_PRODUCED_FILES "${src}") + FOREACH(file ${COMPILER_${lang}_PRODUCED_FILES}) + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Compilation of the ${lang} compiler identification source \"" + "${src}\" produced \"${file}\"\n\n") + ENDFOREACH(file) + + IF(NOT COMPILER_${lang}_PRODUCED_FILES) + # No executable was found. + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Compilation of the ${lang} compiler identification source \"" + "${src}\" did not produce an executable in \"" + "${CMAKE_${lang}_COMPILER_ID_DIR}\".\n\n") + ENDIF(NOT COMPILER_${lang}_PRODUCED_FILES) + ENDIF(CMAKE_${lang}_COMPILER_ID_RESULT) + + # Return the files produced by the compilation. + SET(COMPILER_${lang}_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE) +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) + +#----------------------------------------------------------------------------- +# Function to extract the compiler id from an executable. +FUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) + # Look for a compiler id if not yet known. + IF(NOT CMAKE_${lang}_COMPILER_ID) + # Read the compiler identification string from the executable file. + SET(COMPILER_ID) + SET(PLATFORM_ID) + FILE(STRINGS ${file} + CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 3 REGEX "INFO:") + SET(HAVE_COMPILER_TWICE 0) + FOREACH(info ${CMAKE_${lang}_COMPILER_ID_STRINGS}) + IF("${info}" MATCHES ".*INFO:compiler\\[([^]\"]*)\\].*") + IF(COMPILER_ID) + SET(COMPILER_ID_TWICE 1) + ENDIF(COMPILER_ID) + STRING(REGEX REPLACE ".*INFO:compiler\\[([^]]*)\\].*" "\\1" + COMPILER_ID "${info}") + ENDIF("${info}" MATCHES ".*INFO:compiler\\[([^]\"]*)\\].*") + IF("${info}" MATCHES ".*INFO:platform\\[([^]\"]*)\\].*") + STRING(REGEX REPLACE ".*INFO:platform\\[([^]]*)\\].*" "\\1" + PLATFORM_ID "${info}") + ENDIF("${info}" MATCHES ".*INFO:platform\\[([^]\"]*)\\].*") + IF("${info}" MATCHES ".*INFO:arch\\[([^]\"]*)\\].*") + STRING(REGEX REPLACE ".*INFO:arch\\[([^]]*)\\].*" "\\1" + ARCHITECTURE_ID "${info}") + ENDIF("${info}" MATCHES ".*INFO:arch\\[([^]\"]*)\\].*") + ENDFOREACH(info) + + # Check if a valid compiler and platform were found. + IF(COMPILER_ID AND NOT COMPILER_ID_TWICE) + SET(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}") + SET(CMAKE_${lang}_PLATFORM_ID "${PLATFORM_ID}") + SET(MSVC_${lang}_ARCHITECTURE_ID "${ARCHITECTURE_ID}") + ENDIF(COMPILER_ID AND NOT COMPILER_ID_TWICE) + + # Check the compiler identification string. + IF(CMAKE_${lang}_COMPILER_ID) + # The compiler identification was found. + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "The ${lang} compiler identification is ${CMAKE_${lang}_COMPILER_ID}, found in \"" + "${file}\"\n\n") + ELSE(CMAKE_${lang}_COMPILER_ID) + # The compiler identification could not be found. + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "The ${lang} compiler identification could not be found in \"" + "${file}\"\n\n") + ENDIF(CMAKE_${lang}_COMPILER_ID) + ENDIF(NOT CMAKE_${lang}_COMPILER_ID) + + # try to figure out the executable format: ELF, COFF, Mach-O + IF(NOT CMAKE_EXECUTABLE_FORMAT) + FILE(READ ${file} CMAKE_EXECUTABLE_MAGIC LIMIT 4 HEX) + + # ELF files start with 0x7f"ELF" + IF("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46") + SET(CMAKE_EXECUTABLE_FORMAT "ELF" CACHE INTERNAL "Executable file format") + ENDIF("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46") + +# # COFF (.exe) files start with "MZ" +# IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....") +# SET(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format") +# ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....") +# +# # Mach-O files start with CAFEBABE or FEEDFACE, according to http://radio.weblogs.com/0100490/2003/01/28.html +# IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe") +# SET(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format") +# ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe") +# IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface") +# SET(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format") +# ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface") + + ENDIF(NOT CMAKE_EXECUTABLE_FORMAT) + IF(NOT DEFINED CMAKE_EXECUTABLE_FORMAT) + SET(CMAKE_EXECUTABLE_FORMAT) + ENDIF() + # Return the information extracted. + SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE) + SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE) + SET(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}" + PARENT_SCOPE) + SET(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE) +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang) + +#----------------------------------------------------------------------------- +# Function to query the compiler vendor. +# This uses a table with entries of the form +# list(APPEND CMAKE_${lang}_COMPILER_ID_VENDORS ${vendor}) +# set(CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor} -some-vendor-flag) +# set(CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor} "Some Vendor Output") +# We try running the compiler with the flag for each vendor and +# matching its regular expression in the output. +FUNCTION(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) + + IF(NOT CMAKE_${lang}_COMPILER_ID_DIR) + # We get here when this function is called not from within CMAKE_DETERMINE_COMPILER_ID() + # This is done e.g. for detecting the compiler ID for assemblers. + # Compute the directory in which to run the test and Create a clean working directory. + SET(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CompilerId${lang}) + FILE(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR}) + FILE(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}) + ENDIF(NOT CMAKE_${lang}_COMPILER_ID_DIR) + + + FOREACH(vendor ${CMAKE_${lang}_COMPILER_ID_VENDORS}) + SET(flags ${CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor}}) + SET(regex ${CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor}}) + EXECUTE_PROCESS( + COMMAND ${CMAKE_${lang}_COMPILER} + ${CMAKE_${lang}_COMPILER_ID_ARG1} + ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${flags} + WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR} + OUTPUT_VARIABLE output ERROR_VARIABLE output + RESULT_VARIABLE result + TIMEOUT 10 + ) + + IF("${lang}" STREQUAL "ASM") + MESSAGE(STATUS "Checked for ${vendor}") + MESSAGE(STATUS " Output: -${output}-") + MESSAGE(STATUS " Result: -${result}-") + ENDIF("${lang}" STREQUAL "ASM") + + IF("${output}" MATCHES "${regex}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" " + "matched \"${regex}\":\n${output}") + SET(CMAKE_${lang}_COMPILER_ID "${vendor}" PARENT_SCOPE) + BREAK() + ELSE() + IF("${result}" MATCHES "timeout") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" " + "terminated after 10 s due to timeout.") + ELSE() + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" " + "did not match \"${regex}\":\n${output}") + ENDIF() + ENDIF() + ENDFOREACH() +ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_VENDOR) diff --git a/cmake/Compiler/VISUAL-ASM.cmake b/cmake/Compiler/VISUAL-ASM.cmake new file mode 100644 index 00000000000..0f8019a8e80 --- /dev/null +++ b/cmake/Compiler/VISUAL-ASM.cmake @@ -0,0 +1,2 @@ + +set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;S) diff --git a/cmake/compilerflags.cmake b/cmake/compilerflags.cmake index 2ac31fda4ae..55bd78dd9e1 100644 --- a/cmake/compilerflags.cmake +++ b/cmake/compilerflags.cmake @@ -1,33 +1,24 @@ - -macro(add_compiler_flags) - # Adds the compiler flag to both CMAKE_C_FLAGS and CMAKE_CXX_FLAGS - foreach(flag ${ARGN}) - set(flags_list "${flags_list} ${flag}") - endforeach() - - if(CMAKE_C_FLAGS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flags_list}") - else() - set(CMAKE_C_FLAGS ${flags_list}) - endif() - - if(CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flags_list}") - else() - set(CMAKE_CXX_FLAGS ${flags_list}) - endif() -endmacro() - -macro(add_linkerflag MODULE _flag) - set(NEW_LINKER_FLAGS ${_flag}) - get_target_property(LINKER_FLAGS ${MODULE} LINK_FLAGS) - if(LINKER_FLAGS) - set(NEW_LINKER_FLAGS "${LINKER_FLAGS} ${NEW_LINKER_FLAGS}") - endif() - set_target_properties(${MODULE} PROPERTIES LINK_FLAGS ${NEW_LINKER_FLAGS}) -endmacro() - -macro(set_unicode) - add_definitions(-DUNICODE -D_UNICODE) - set(IS_UNICODE 1) -endmacro() + +function(add_compiler_flags) + # Adds the compiler flag to both CMAKE_C_FLAGS and CMAKE_CXX_FLAGS + foreach(flag ${ARGN}) + set(flags_list "${flags_list} ${flag}") + endforeach() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flags_list}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flags_list}" PARENT_SCOPE) +endfunction() + +function(add_linkerflag MODULE _flag) + set(NEW_LINKER_FLAGS ${_flag}) + get_target_property(LINKER_FLAGS ${MODULE} LINK_FLAGS) + if(LINKER_FLAGS) + set(NEW_LINKER_FLAGS "${LINKER_FLAGS} ${NEW_LINKER_FLAGS}") + endif() + set_target_properties(${MODULE} PROPERTIES LINK_FLAGS ${NEW_LINKER_FLAGS}) +endfunction() + +macro(set_unicode) + add_definitions(-DUNICODE -D_UNICODE) + set(IS_UNICODE 1) +endmacro() diff --git a/cmake/gcc.cmake b/cmake/gcc.cmake index 867c52b13d0..f2229d18821 100644 --- a/cmake/gcc.cmake +++ b/cmake/gcc.cmake @@ -37,7 +37,7 @@ endif() add_compiler_flags(-fno-strict-aliasing) if(ARCH MATCHES i386) - add_compiler_flags(-mpreferred-stack-boundary=2 -fno-set-stack-executable -fno-optimize-sibling-calls) + add_compiler_flags(-mpreferred-stack-boundary=2 -fno-set-stack-executable -fno-optimize-sibling-calls -fno-omit-frame-pointer) if(OPTIMIZE STREQUAL "1") add_compiler_flags(-ftracer -momit-leaf-frame-pointer) endif() @@ -78,7 +78,7 @@ set(CMAKE_C_LINK_EXECUTABLE " -o ") -set(CMAKE_EXE_LINKER_FLAGS "-nodefaultlibs -nostdlib -Wl,--enable-auto-image-base -Wl,--disable-auto-import") +set(CMAKE_EXE_LINKER_FLAGS "-nodefaultlibs -nostdlib -Wl,--enable-auto-image-base -Wl,--disable-auto-import -Wl,--disable-stdcall-fixup") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} -Wl,--disable-stdcall-fixup") @@ -165,6 +165,7 @@ macro(set_module_type MODULE TYPE) add_dependencies(${MODULE} bugcodes) elseif(${TYPE} MATCHES nativedll) set_subsystem(${MODULE} native) + set_entrypoint(${MODULE} DllMain 12) else() message(FATAL_ERROR "Unknown module type : ${TYPE}") endif() @@ -199,14 +200,6 @@ elseif(ARCH MATCHES amd64) set(IDL_FLAGS -m64 --win64) endif() -set(IDL_HEADER_ARG -h -o) #.h -set(IDL_TYPELIB_ARG -t -o) #.tlb -set(IDL_SERVER_ARG -s -S) #.c for server library -set(IDL_CLIENT_ARG -c -C) #.c for stub client library -set(IDL_PROXY_ARG -p -P) -set(IDL_INTERFACE_ARG -u -o) -set(IDL_DLLDATA_ARG --dlldata-only -o) - macro(add_delay_importlibs MODULE) foreach(LIB ${ARGN}) target_link_libraries(${MODULE} ${CMAKE_BINARY_DIR}/importlibs/lib${LIB}_delayed.a) @@ -293,44 +286,69 @@ endmacro() set(PSEH_LIB "pseh") # Macros -macro(_PCH_GET_COMPILE_FLAGS _target_name _out_compile_flags _header_filename) - # Add the precompiled header to the build - get_filename_component(_FILE ${_header_filename} NAME) - set(_gch_filename "${_FILE}.gch") - list(APPEND ${_out_compile_flags} -c ${_header_filename} -o ${_gch_filename}) - - # This gets us our includes - get_directory_property(DIRINC INCLUDE_DIRECTORIES) - foreach(item ${DIRINC}) - list(APPEND ${_out_compile_flags} -I${item}) - endforeach() +if(PCH) + macro(_PCH_GET_COMPILE_FLAGS _target_name _out_compile_flags _header_filename) + # Add the precompiled header to the build + get_filename_component(_FILE ${_header_filename} NAME) + set(_gch_filename "${_FILE}.gch") + list(APPEND ${_out_compile_flags} -c ${_header_filename} -o ${_gch_filename}) + + # This gets us our includes + get_directory_property(DIRINC INCLUDE_DIRECTORIES) + foreach(item ${DIRINC}) + list(APPEND ${_out_compile_flags} -I${item}) + endforeach() - # This our definitions - get_directory_property(_compiler_flags DEFINITIONS) - list(APPEND ${_out_compile_flags} ${_compiler_flags}) + # This our definitions + get_directory_property(_compiler_flags DEFINITIONS) + list(APPEND ${_out_compile_flags} ${_compiler_flags}) - # This gets any specific definitions that were added with set-target-property - get_target_property(_target_defs ${_target_name} COMPILE_DEFINITIONS) - if (_target_defs) - foreach(item ${_target_defs}) - list(APPEND ${_out_compile_flags} -D${item}) - endforeach() - endif() + # This gets any specific definitions that were added with set-target-property + get_target_property(_target_defs ${_target_name} COMPILE_DEFINITIONS) + if (_target_defs) + foreach(item ${_target_defs}) + list(APPEND ${_out_compile_flags} -D${item}) + endforeach() + endif() - separate_arguments(${_out_compile_flags}) -endmacro() + if(IS_CPP) + list(APPEND ${_out_compile_flags} ${CMAKE_CXX_FLAGS}) + else() + list(APPEND ${_out_compile_flags} ${CMAKE_C_FLAGS}) + endif() -macro(add_pch _target_name _FILE) - #set(_header_filename ${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}) - #get_filename_component(_basename ${_FILE} NAME) - #set(_gch_filename ${_basename}.gch) - #_PCH_GET_COMPILE_FLAGS(${_target_name} _args ${_header_filename}) + separate_arguments(${_out_compile_flags}) + endmacro() - #add_custom_command(OUTPUT ${_gch_filename} COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} ${_args} DEPENDS ${_header_filename}) - #get_target_property(_src_files ${_target_name} SOURCES) - #set_source_files_properties(${_src_files} PROPERTIES COMPILE_FLAGS "-Winvalid-pch -fpch-preprocess" #OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_gch_filename}) - #add_linkerflag(${_target_name} "${_gch_filename}") -endmacro() + macro(add_pch _target_name _FILE) + set(_header_filename ${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}) + get_filename_component(_basename ${_FILE} NAME) + set(_gch_filename ${_basename}.gch) + _PCH_GET_COMPILE_FLAGS(${_target_name} _args ${_header_filename}) + + if(IS_CPP) + set(__lang CXX) + set(__compiler ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}) + else() + set(__lang C) + set(__compiler ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}) + endif() + + add_custom_command(OUTPUT ${_gch_filename} COMMAND ${__compiler} ${_args} IMPLICIT_DEPENDS ${__lang} ${_header_filename}) + get_target_property(_src_files ${_target_name} SOURCES) + foreach(_item in ${_src_files}) + get_source_file_property(__src_lang ${_item} LANGUAGE) + if(__src_lang STREQUAL __lang) + set_source_files_properties(${_item} PROPERTIES COMPILE_FLAGS "-fpch-preprocess" OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_gch_filename}) + endif() + endforeach() + #set dependency checking : depends on precompiled header only whixh already depends on deeper header + set_target_properties(${_target_name} PROPERTIES IMPLICIT_DEPENDS_INCLUDE_TRANSFORM "\"${_basename}\"=;<${_basename}>=") + endmacro() +else() + macro(add_pch _target_name _FILE) + endmacro() +endif() macro(CreateBootSectorTarget _target_name _asm_file _object_file _base_address) get_filename_component(OBJECT_PATH ${_object_file} PATH) diff --git a/cmake/idl-support.cmake b/cmake/idl-support.cmake index a64df0da6e4..ee3f51b4622 100644 --- a/cmake/idl-support.cmake +++ b/cmake/idl-support.cmake @@ -86,21 +86,28 @@ macro(add_rpcproxy_files) if(MSVC) set(DLLDATA_ARG /dlldata ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c) + set(DLLDATA_DEPENDENCIES "") endif() foreach(FILE ${ARGN}) get_filename_component(NAME ${FILE} NAME_WE) - if(NOT MSVC) + if(MSVC) + set(DLLDATA_DEPENDENCIES ${DLLDATA_DEPENDENCIES} ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c) + else() list(APPEND IDLS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) endif() add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c ${NAME}_p.h + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.h COMMAND ${IDL_COMPILER} ${INCLUDES} ${DEFINES} ${IDL_FLAGS} ${IDL_PROXY_ARG} ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c ${IDL_HEADER_ARG2} ${NAME}_p.h ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} ${DLLDATA_ARG} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) endforeach() # Extra pass to generate dlldata if(MSVC) - #nobody told how to generate it, so mark it as generated + #touch it, so we're sure it's older than its dependencies + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c + DEPENDS ${DLLDATA_DEPENDENCIES}) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c PROPERTIES GENERATED TRUE) else() add_custom_command( diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake index af42d92d9b1..9e301a4363a 100644 --- a/cmake/msvc.cmake +++ b/cmake/msvc.cmake @@ -1,221 +1,225 @@ - -if(${CMAKE_BUILD_TYPE} MATCHES Debug) - # no optimitation -elseif(OPTIMIZE STREQUAL "1") - add_definitions(/O1) -elseif(OPTIMIZE STREQUAL "2") - add_definitions(/O2) -elseif(OPTIMIZE STREQUAL "3") - add_definitions(/Ot /Ox /GS-) -elseif(OPTIMIZE STREQUAL "4") - add_definitions(/Os /Ox /GS-) -elseif(OPTIMIZE STREQUAL "5") - add_definitions(/GF /Gy /Ob2 /Os /Ox /GS-) -endif() - -if(ARCH MATCHES i386) - add_definitions(/DWIN32 /D_WINDOWS) -endif() - -add_definitions(/Dinline=__inline /D__STDC__=1) - -add_compiler_flags(/X /GR- /GS- /Zl /W3) - -if(${_MACHINE_ARCH_FLAG} MATCHES X86) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB") -endif() - -if(${ARCH} MATCHES amd64) - add_definitions(/D__x86_64) - set(SPEC2DEF_ARCH x86_64) -else() - set(SPEC2DEF_ARCH i386) -endif() - -link_directories(${REACTOS_SOURCE_DIR}/importlibs ${REACTOS_BINARY_DIR}/importlibs ${REACTOS_BINARY_DIR}/lib/sdk/crt) - -set(CMAKE_RC_COMPILE_OBJECT " /I${REACTOS_SOURCE_DIR}/include/psdk /I${REACTOS_BINARY_DIR}/include/psdk /I${REACTOS_SOURCE_DIR}/include /I${REACTOS_SOURCE_DIR}/include/reactos /I${REACTOS_BINARY_DIR}/include/reactos /I${REACTOS_SOURCE_DIR}/include/reactos/wine /I${REACTOS_SOURCE_DIR}/include/crt /I${REACTOS_SOURCE_DIR}/include/crt/mingw32 /fo ") - -if(MSVC_IDE) - # Asm source files are not supported in VS generators yet. As a result, isn't recognized. - # We may temporarily use just the global defines, but this is not a solution as some modules (minihal for example) apply additional definitions to source files, so we get an incorrect build of such targets. - get_directory_property(definitions DEFINITIONS) - set(CMAKE_ASM_COMPILE_OBJECT - " /nologo /X /I${REACTOS_SOURCE_DIR}/include/asm /I${REACTOS_BINARY_DIR}/include/asm ${definitions} /D__ASM__ /D_USE_ML /EP /c > .tmp" - " /nologo /Cp /Fo /c /Ta .tmp") -else() - # NMake Makefiles - set(CMAKE_ASM_COMPILE_OBJECT - " /nologo /X /I${REACTOS_SOURCE_DIR}/include/asm /I${REACTOS_BINARY_DIR}/include/asm /D__ASM__ /D_USE_ML /EP /c > .tmp" - " /nologo /Cp /Fo /c /Ta .tmp") -endif() - -set(CMAKE_RC_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) -set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) -set(CMAKE_ASM_CREATE_STATIC_LIBRARY ${CMAKE_C_CREATE_STATIC_LIBRARY}) - -macro(add_pch _target_name _FILE) -endmacro() - -macro(set_entrypoint MODULE ENTRYPOINT) - if(${ENTRYPOINT} STREQUAL "0") - add_linkerflag(${MODULE} "/NOENTRY") - else() - add_linkerflag(${MODULE} "/ENTRY:${ENTRYPOINT}") - endif() -endmacro() - -macro(set_subsystem MODULE SUBSYSTEM) - add_linkerflag(${MODULE} "/subsystem:${SUBSYSTEM}") -endmacro() - -macro(set_image_base MODULE IMAGE_BASE) - add_linkerflag(${MODULE} "/BASE:${IMAGE_BASE}") -endmacro() - -macro(set_module_type MODULE TYPE) - add_dependencies(${MODULE} psdk) - if(${TYPE} MATCHES nativecui) - set_subsystem(${MODULE} native) - set_entrypoint(${MODULE} NtProcessStartup@4) - elseif (${TYPE} MATCHES win32gui) - set_subsystem(${MODULE} windows) - if(IS_UNICODE) - set_entrypoint(${MODULE} wWinMainCRTStartup) - else() - set_entrypoint(${MODULE} WinMainCRTStartup) - endif(IS_UNICODE) - elseif (${TYPE} MATCHES win32cui) - set_subsystem(${MODULE} console) - if(IS_UNICODE) - set_entrypoint(${MODULE} wmainCRTStartup) - else() - set_entrypoint(${MODULE} mainCRTStartup) - endif(IS_UNICODE) - elseif(${TYPE} MATCHES win32dll) - # Need this only because mingw library is broken - set_entrypoint(${MODULE} DllMainCRTStartup@12) - if(DEFINED baseaddress_${MODULE}) - set_image_base(${MODULE} ${baseaddress_${MODULE}}) - else() - message(STATUS "${MODULE} has no base address") - endif() - add_linkerflag(${MODULE} "/DLL") - elseif(${TYPE} MATCHES win32ocx) - set_entrypoint(${MODULE} DllMainCRTStartup@12) - set_target_properties(${MODULE} PROPERTIES SUFFIX ".ocx") - add_linkerflag(${MODULE} "/DLL") - elseif(${TYPE} MATCHES cpl) - set_entrypoint(${MODULE} DllMainCRTStartup@12) - set_target_properties(${MODULE} PROPERTIES SUFFIX ".cpl") - add_linkerflag(${MODULE} "/DLL") - elseif(${TYPE} MATCHES kernelmodedriver) - set_target_properties(${MODULE} PROPERTIES SUFFIX ".sys") - set_entrypoint(${MODULE} DriverEntry@8) - set_subsystem(${MODULE} native) - set_image_base(${MODULE} 0x00010000) - add_linkerflag(${MODULE} "/DRIVER") - add_dependencies(${MODULE} bugcodes) - endif() -endmacro() - -macro(set_rc_compiler) -# dummy, this workaround is only needed in mingw due to lack of RC support in cmake -endmacro() - -# Thanks MS for creating a stupid linker -macro(add_importlib_target _exports_file) - get_filename_component(_name ${_exports_file} NAME_WE) - get_target_property(_suffix ${_name} SUFFIX) - if(${_suffix} STREQUAL "_suffix-NOTFOUND") - get_target_property(_type ${_name} TYPE) - if(${_type} MATCHES EXECUTABLE) - set(_suffix ".exe") - else() - set(_suffix ".dll") - endif() - endif() - - # Generate the asm stub file and the export def file - add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def - COMMAND native-spec2def --ms --kill-at -a=${SPEC2DEF_ARCH} --implib -n=${_name}${_suffix} -d=${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def -l=${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file}) - - # Assemble the stub file - add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj - COMMAND ${CMAKE_ASM_COMPILER} /nologo /Cp /Fo${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj /c /Ta ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm - DEPENDS "${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm") - - # Add neccessary importlibs for redirections - set(_libraries "") - foreach(_lib ${ARGN}) - list(APPEND _libraries "${CMAKE_BINARY_DIR}/importlibs/${_lib}.lib") - list(APPEND _dependencies ${_lib}) - endforeach() - - # Build the importlib - add_custom_command( - OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.lib - COMMAND LINK /LIB /NOLOGO /DEF:${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def /OUT:${CMAKE_BINARY_DIR}/importlibs/lib${_name}.lib ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj ${_libraries} - DEPENDS ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def) - - # Add the importlib target - add_custom_target( - lib${_name} - DEPENDS ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.lib) - - add_dependencies(lib${_name} asm ${_dependencies}) -endmacro() - -macro(add_delay_importlibs MODULE) - # TODO. For now forward to normal import libs - add_importlibs(${MODULE} ${ARGN}) -endmacro() - -macro(spec2def _dllname _spec_file) - get_filename_component(_file ${_spec_file} NAME_WE) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_file}.def ${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c - COMMAND native-spec2def --ms --kill-at -a=${SPEC2DEF_ARCH} -n=${_dllname} -d=${CMAKE_CURRENT_BINARY_DIR}/${_file}.def -s=${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}) - set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_file}.def ${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c - PROPERTIES GENERATED TRUE) -endmacro() - -macro(macro_mc FILE) - set(COMMAND_MC mc -r ${REACTOS_BINARY_DIR}/include/reactos -h ${REACTOS_BINARY_DIR}/include/reactos ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.mc) -endmacro() - -file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/importlibs) - -#pseh workaround -set(PSEH_LIB "pseh") - -macro(CreateBootSectorTarget2 _target_name _asm_file _binary_file _base_address) - - set(_object_file ${_binary_file}.obj) - set(_temp_file ${_binary_file}.tmp) - - add_custom_command( - OUTPUT ${_temp_file} - COMMAND ${CMAKE_C_COMPILER} /nologo /X /I${REACTOS_SOURCE_DIR}/include/asm /I${REACTOS_BINARY_DIR}/include/asm /D__ASM__ /D_USE_ML /EP /c ${_asm_file} > ${_temp_file} - DEPENDS ${_asm_file}) - - add_custom_command( - OUTPUT ${_object_file} - COMMAND ml /nologo /Cp /Fo${_object_file} /c /Ta ${_temp_file} - DEPENDS ${_temp_file}) - - add_custom_command( - OUTPUT ${_binary_file} - COMMAND native-obj2bin ${_object_file} ${_binary_file} ${_base_address} - DEPENDS ${_object_file}) - - set_source_files_properties(${_object_file} ${_temp_file} ${_binary_file} PROPERTIES GENERATED TRUE) - - add_custom_target(${_target_name} ALL DEPENDS ${_binary_file}) -endmacro() + +if(${CMAKE_BUILD_TYPE} MATCHES Debug) + # no optimitation +elseif(OPTIMIZE STREQUAL "1") + add_definitions(/O1) +elseif(OPTIMIZE STREQUAL "2") + add_definitions(/O2) +elseif(OPTIMIZE STREQUAL "3") + add_definitions(/Ot /Ox /GS-) +elseif(OPTIMIZE STREQUAL "4") + add_definitions(/Os /Ox /GS-) +elseif(OPTIMIZE STREQUAL "5") + add_definitions(/GF /Gy /Ob2 /Os /Ox /GS-) +endif() + +if(ARCH MATCHES i386) + add_definitions(/DWIN32 /D_WINDOWS) +endif() + +add_definitions(/Dinline=__inline /D__STDC__=1) + +add_compiler_flags(/X /GR- /GS- /Zl /W3) + +if(${_MACHINE_ARCH_FLAG} MATCHES X86) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO /NODEFAULTLIB") +endif() + +if(${ARCH} MATCHES amd64) + add_definitions(/D__x86_64) + set(SPEC2DEF_ARCH x86_64) +else() + set(SPEC2DEF_ARCH i386) +endif() + +link_directories(${REACTOS_SOURCE_DIR}/importlibs ${REACTOS_BINARY_DIR}/importlibs ${REACTOS_BINARY_DIR}/lib/sdk/crt) + +set(CMAKE_RC_COMPILE_OBJECT " /I${REACTOS_SOURCE_DIR}/include/psdk /I${REACTOS_BINARY_DIR}/include/psdk /I${REACTOS_SOURCE_DIR}/include /I${REACTOS_SOURCE_DIR}/include/reactos /I${REACTOS_BINARY_DIR}/include/reactos /I${REACTOS_SOURCE_DIR}/include/reactos/wine /I${REACTOS_SOURCE_DIR}/include/crt /I${REACTOS_SOURCE_DIR}/include/crt/mingw32 /fo ") + +if(MSVC_IDE) + # Asm source files are not supported in VS generators yet. As a result, isn't recognized. + # We may temporarily use just the global defines, but this is not a solution as some modules (minihal for example) apply additional definitions to source files, so we get an incorrect build of such targets. + get_directory_property(definitions DEFINITIONS) + set(CMAKE_ASM_COMPILE_OBJECT + " /nologo /X /I${REACTOS_SOURCE_DIR}/include/asm /I${REACTOS_BINARY_DIR}/include/asm ${definitions} /D__ASM__ /D_USE_ML /EP /c > .tmp" + " /nologo /Cp /Fo /c /Ta .tmp") +else() + # NMake Makefiles + set(CMAKE_ASM_COMPILE_OBJECT + " /nologo /X /I${REACTOS_SOURCE_DIR}/include/asm /I${REACTOS_BINARY_DIR}/include/asm /D__ASM__ /D_USE_ML /EP /c > .tmp" + " /nologo /Cp /Fo /c /Ta .tmp") +endif() + +set(CMAKE_RC_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) +set(CMAKE_ASM_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) +set(CMAKE_ASM_CREATE_STATIC_LIBRARY ${CMAKE_C_CREATE_STATIC_LIBRARY}) + +macro(add_pch _target_name _FILE) +endmacro() + +macro(set_entrypoint MODULE ENTRYPOINT) + if(${ENTRYPOINT} STREQUAL "0") + add_linkerflag(${MODULE} "/NOENTRY") + else() + add_linkerflag(${MODULE} "/ENTRY:${ENTRYPOINT}") + endif() +endmacro() + +macro(set_subsystem MODULE SUBSYSTEM) + add_linkerflag(${MODULE} "/subsystem:${SUBSYSTEM}") +endmacro() + +macro(set_image_base MODULE IMAGE_BASE) + add_linkerflag(${MODULE} "/BASE:${IMAGE_BASE}") +endmacro() + +macro(set_module_type MODULE TYPE) + add_dependencies(${MODULE} psdk) + if(${TYPE} MATCHES nativecui) + set_subsystem(${MODULE} native) + set_entrypoint(${MODULE} NtProcessStartup@4) + elseif (${TYPE} MATCHES win32gui) + set_subsystem(${MODULE} windows) + if(IS_UNICODE) + set_entrypoint(${MODULE} wWinMainCRTStartup) + else() + set_entrypoint(${MODULE} WinMainCRTStartup) + endif(IS_UNICODE) + elseif (${TYPE} MATCHES win32cui) + set_subsystem(${MODULE} console) + if(IS_UNICODE) + set_entrypoint(${MODULE} wmainCRTStartup) + else() + set_entrypoint(${MODULE} mainCRTStartup) + endif(IS_UNICODE) + elseif(${TYPE} MATCHES win32dll) + # Need this only because mingw library is broken + set_entrypoint(${MODULE} DllMainCRTStartup@12) + if(DEFINED baseaddress_${MODULE}) + set_image_base(${MODULE} ${baseaddress_${MODULE}}) + else() + message(STATUS "${MODULE} has no base address") + endif() + add_linkerflag(${MODULE} "/DLL") + elseif(${TYPE} MATCHES win32ocx) + set_entrypoint(${MODULE} DllMainCRTStartup@12) + set_target_properties(${MODULE} PROPERTIES SUFFIX ".ocx") + add_linkerflag(${MODULE} "/DLL") + elseif(${TYPE} MATCHES cpl) + set_entrypoint(${MODULE} DllMainCRTStartup@12) + set_target_properties(${MODULE} PROPERTIES SUFFIX ".cpl") + add_linkerflag(${MODULE} "/DLL") + elseif(${TYPE} MATCHES kernelmodedriver) + set_target_properties(${MODULE} PROPERTIES SUFFIX ".sys") + set_entrypoint(${MODULE} DriverEntry@8) + set_subsystem(${MODULE} native) + set_image_base(${MODULE} 0x00010000) + add_linkerflag(${MODULE} "/DRIVER") + add_dependencies(${MODULE} bugcodes) + elseif(${TYPE} MATCHES nativedll) + set_subsystem(${MODULE} native) + else() + message(FATAL_ERROR "Unknown module type : ${TYPE}") + endif() +endmacro() + +macro(set_rc_compiler) +# dummy, this workaround is only needed in mingw due to lack of RC support in cmake +endmacro() + +# Thanks MS for creating a stupid linker +macro(add_importlib_target _exports_file) + get_filename_component(_name ${_exports_file} NAME_WE) + get_target_property(_suffix ${_name} SUFFIX) + if(${_suffix} STREQUAL "_suffix-NOTFOUND") + get_target_property(_type ${_name} TYPE) + if(${_type} MATCHES EXECUTABLE) + set(_suffix ".exe") + else() + set(_suffix ".dll") + endif() + endif() + + # Generate the asm stub file and the export def file + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def + COMMAND native-spec2def --ms --kill-at -a=${SPEC2DEF_ARCH} --implib -n=${_name}${_suffix} -d=${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def -l=${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file}) + + # Assemble the stub file + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj + COMMAND ${CMAKE_ASM_COMPILER} /nologo /Cp /Fo${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj /c /Ta ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm + DEPENDS "${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.asm") + + # Add neccessary importlibs for redirections + set(_libraries "") + foreach(_lib ${ARGN}) + list(APPEND _libraries "${CMAKE_BINARY_DIR}/importlibs/${_lib}.lib") + list(APPEND _dependencies ${_lib}) + endforeach() + + # Build the importlib + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.lib + COMMAND LINK /LIB /NOLOGO /DEF:${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def /OUT:${CMAKE_BINARY_DIR}/importlibs/lib${_name}.lib ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj ${_libraries} + DEPENDS ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_stubs.obj ${CMAKE_BINARY_DIR}/importlibs/lib${_name}_exp.def) + + # Add the importlib target + add_custom_target( + lib${_name} + DEPENDS ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.lib) + + add_dependencies(lib${_name} asm ${_dependencies}) +endmacro() + +macro(add_delay_importlibs MODULE) + # TODO. For now forward to normal import libs + add_importlibs(${MODULE} ${ARGN}) +endmacro() + +macro(spec2def _dllname _spec_file) + get_filename_component(_file ${_spec_file} NAME_WE) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_file}.def ${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c + COMMAND native-spec2def --ms --kill-at -a=${SPEC2DEF_ARCH} -n=${_dllname} -d=${CMAKE_CURRENT_BINARY_DIR}/${_file}.def -s=${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_file}.def ${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c + PROPERTIES GENERATED TRUE) +endmacro() + +macro(macro_mc FILE) + set(COMMAND_MC mc -r ${REACTOS_BINARY_DIR}/include/reactos -h ${REACTOS_BINARY_DIR}/include/reactos ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.mc) +endmacro() + +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/importlibs) + +#pseh workaround +set(PSEH_LIB "pseh") + +macro(CreateBootSectorTarget2 _target_name _asm_file _binary_file _base_address) + + set(_object_file ${_binary_file}.obj) + set(_temp_file ${_binary_file}.tmp) + + add_custom_command( + OUTPUT ${_temp_file} + COMMAND ${CMAKE_C_COMPILER} /nologo /X /I${REACTOS_SOURCE_DIR}/include/asm /I${REACTOS_BINARY_DIR}/include/asm /D__ASM__ /D_USE_ML /EP /c ${_asm_file} > ${_temp_file} + DEPENDS ${_asm_file}) + + add_custom_command( + OUTPUT ${_object_file} + COMMAND ml /nologo /Cp /Fo${_object_file} /c /Ta ${_temp_file} + DEPENDS ${_temp_file}) + + add_custom_command( + OUTPUT ${_binary_file} + COMMAND native-obj2bin ${_object_file} ${_binary_file} ${_base_address} + DEPENDS ${_object_file}) + + set_source_files_properties(${_object_file} ${_temp_file} ${_binary_file} PROPERTIES GENERATED TRUE) + + add_custom_target(${_target_name} ALL DEPENDS ${_binary_file}) +endmacro() diff --git a/configure.cmd b/configure.cmd index 46add19610b..99dcb4e8975 100644 --- a/configure.cmd +++ b/configure.cmd @@ -5,26 +5,34 @@ set REACTOS_SOURCE_DIR=%~dp0 set USE_NMAKE=0 :: Detect presence of cmake - cmd /c cmake --version 2>&1 | find "cmake version" > NUL || goto cmake_notfound +cmd /c cmake --version 2>&1 | find "cmake version" > NUL || goto cmake_notfound :: Detect build environment (MinGW, VS, WDK, ...) if defined ROS_ARCH ( + echo Detected RosBE for %ROS_ARCH% set BUILD_ENVIRONMENT=MinGW set ARCH=%ROS_ARCH% - echo Detected RosBE for %ROS_ARCH% + if /I "%1" == "Codeblocks" ( + set CMAKE_GENERATOR="CodeBlocks - MinGW Makefiles" + ) else if /I "%1" == "Eclipse" ( + set CMAKE_GENERATOR="Eclipse CDT4 - MinGW Makefiles" + ) else ( + set CMAKE_GENERATOR="MinGW Makefiles" + ) + ) else if defined DDK_TARGET_OS ( + echo Detected DDK/WDK for %DDK_TARGET_OS%-%_BUILDARCH%% + set BUILD_ENVIRONMENT=WDK if "%_BUILDARCH%" == "x86" ( set ARCH=i386 - ) - if "%_BUILDARCH%" == "AMD64" ( + ) else if "%_BUILDARCH%" == "AMD64" ( set ARCH=amd64 ) - set BUILD_ENVIRONMENT=WDK set USE_NMAKE=1 set USE_WDK_HEADERS=0 - echo Detected DDK/WDK for %DDK_TARGET_OS%-%ARCH% -)else if defined VCINSTALLDIR ( -:: VS command prompt does not put this in enviroment vars + +) else if defined VCINSTALLDIR ( + :: VS command prompt does not put this in enviroment vars cl 2>&1 | find "x86" > NUL && set ARCH=i386 cl 2>&1 | find "x64" > NUL && set ARCH=amd64 cl 2>&1 | find "14." > NUL && set BUILD_ENVIRONMENT=VS8 @@ -34,35 +42,66 @@ if defined ROS_ARCH ( echo Error: Visual Studio version too old or version detection failed. exit /b ) + echo Detected Visual Studio Environment %BUILD_ENVIRONMENT%-%ARCH% - if /I not "%1" == "VSSolution" ( + if /I "%1" == "VSSolution" ( + if "%BUILD_ENVIRONMENT%" == "VS8" ( + if "%ARCH%" == "amd64" ( + set CMAKE_GENERATOR="Visual Studio 8 2005 Win64" + ) else ( + set CMAKE_GENERATOR="Visual Studio 8 2005" + ) + ) else if "%BUILD_ENVIRONMENT%" == "VS9" ( + if "%ARCH%" == "amd64" ( + set CMAKE_GENERATOR="Visual Studio 9 2008 Win64" + ) else ( + set CMAKE_GENERATOR="Visual Studio 9 2008" + ) + ) else if "%BUILD_ENVIRONMENT%" == "VS10" ( + if "%ARCH%" == "amd64" ( + set CMAKE_GENERATOR="Visual Studio 10 Win64" + ) else ( + set CMAKE_GENERATOR="Visual Studio 10" + ) + ) + ) else ( set USE_NMAKE=1 echo This script defaults to nmake. To use Visual Studio GUI specify "VSSolution" as a parameter. ) + ) else if defined sdkdir ( + echo Detected Windows SDK %TARGET_PLATFORM%-%TARGET_CPU% if "%TARGET_CPU%" == "x86" ( set ARCH=i386 - ) - if "%TARGET_CPU%" == "x64" ( + ) else if "%TARGET_CPU%" == "x64" ( set ARCH=amd64 ) + set BUILD_ENVIRONMENT=SDK set USE_NMAKE=1 - echo Detected Windows SDK %TARGET_PLATFORM%-%ARCH% -) -:: Detect NMAKE JOM -if %USE_NMAKE% == 1 ( - cmd /c jom /version 2>&1 | find "jom version" > NUL && set USE_NMAKE=2 +) else ( + echo Error: Unable to detect build environment. Configure script failure. + exit /b ) :: Checkpoint if not defined ARCH ( - goto fail + echo unknown build architecture + exit /b ) -if not defined BUILD_ENVIRONMENT ( - goto fail +:: Detect nmake generator +if %USE_NMAKE% == 1 ( + if /I "%1" == "CodeBlocks" ( + set CMAKE_GENERATOR="CodeBlocks - NMake Makefiles" + ) else if /I "%1" == "Eclipse" ( + set CMAKE_GENERATOR="Eclipse CDT4 - NMake Makefiles" + ) else if /I "%1" == "JOM" ( + set CMAKE_GENERATOR="NMake Makefiles JOM" + ) else ( + set CMAKE_GENERATOR="NMake Makefiles" + ) ) :: Create directories @@ -90,43 +129,7 @@ if EXIST CMakeCache.txt ( ) set REACTOS_BUILD_TOOLS_DIR=%CD% -if "%BUILD_ENVIRONMENT%" == "MinGW" ( - if /I "%1" == "Codeblocks" ( - cmake -G "CodeBlocks - MinGW Makefiles" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else if /I "%1" == "Eclipse" ( - cmake -G "Eclipse CDT4 - MinGW Makefiles" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "MinGW Makefiles" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) -) else if defined USE_NMAKE ( - if /I "%1" == "CodeBlocks" ( - cmake -G "CodeBlocks - NMake Makefiles" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else if /I "%1" == "Eclipse" ( - cmake -G "Eclipse CDT4 - NMake Makefiles" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else if %USE_NMAKE% == 2 ( - cmake -G "NMake Makefiles JOM" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "NMake Makefiles" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) -) else if "%BUILD_ENVIRONMENT%" == "VS8" ( - if "%ARCH%" == "amd64" ( - cmake -G "Visual Studio 8 2005 Win64" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "Visual Studio 8 2005" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) -) else if "%BUILD_ENVIRONMENT%" == "VS9" ( - if "%ARCH%" == "amd64" ( - cmake -G "Visual Studio 9 2008 Win64" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "Visual Studio 9 2008" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) -) else if "%BUILD_ENVIRONMENT%" == "VS10" ( - if "%ARCH%" == "amd64" ( - cmake -G "Visual Studio 10 Win64" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "Visual Studio 10" -DARCH=%ARCH% %REACTOS_SOURCE_DIR% - ) -) +cmake -G %CMAKE_GENERATOR% -DARCH=%ARCH% %REACTOS_SOURCE_DIR% cd.. echo Preparing reactos... @@ -136,41 +139,11 @@ if EXIST CMakeCache.txt ( ) if "%BUILD_ENVIRONMENT%" == "MinGW" ( - if /I "%1" == "CodeBlocks" ( - cmake -G "CodeBlocks - MinGW Makefiles" -DENABLE_CCACHE=0 -DCMAKE_TOOLCHAIN_FILE=toolchain-gcc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else if /I "%1" == "Eclipse" ( - cmake -G "Eclipse CDT4 - MinGW Makefiles" -DENABLE_CCACHE=0 -DCMAKE_TOOLCHAIN_FILE=toolchain-gcc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "MinGW Makefiles" -DENABLE_CCACHE=0 -DCMAKE_TOOLCHAIN_FILE=toolchain-gcc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) -) else if defined USE_NMAKE ( - if /I "%1" == "CodeBlocks" ( - cmake -G "CodeBlocks - NMake Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DUSE_WDK_HEADERS=%USE_WDK_HEADERS% -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else if /I "%1" == "Eclipse" ( - cmake -G "Eclipse CDT4 - NMake Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DUSE_WDK_HEADERS=%USE_WDK_HEADERS% -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else if %USE_NMAKE% == 2 ( - cmake -G "NMake Makefiles JOM" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DUSE_WDK_HEADERS=%USE_WDK_HEADERS% -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "NMake Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DUSE_WDK_HEADERS=%USE_WDK_HEADERS% -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) -) else if "%BUILD_ENVIRONMENT%" == "VS8" ( - if "%ARCH%" == "amd64" ( - cmake -G "Visual Studio 8 2005 Win64" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "Visual Studio 8 2005" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) -) else if "%BUILD_ENVIRONMENT%" == "VS9" ( - if "%ARCH%" == "amd64" ( - cmake -G "Visual Studio 9 2008 Win64" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "Visual Studio 9 2008" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) -) else if "%BUILD_ENVIRONMENT%" == "VS10" ( - if "%ARCH%" == "amd64" ( - cmake -G "Visual Studio 10 Win64" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) else ( - cmake -G "Visual Studio 10" -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% - ) + cmake -G %CMAKE_GENERATOR% -DENABLE_CCACHE=0 -DPCH=0 -DCMAKE_TOOLCHAIN_FILE=toolchain-gcc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% +) else if "%BUILD_ENVIRONMENT%" == "WDK" ( + cmake -G %CMAKE_GENERATOR% -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DUSE_WDK_HEADERS=%USE_WDK_HEADERS% -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% +) else ( + cmake -G %CMAKE_GENERATOR% -DCMAKE_TOOLCHAIN_FILE=toolchain-msvc.cmake -DARCH=%ARCH% -DREACTOS_BUILD_TOOLS_DIR:DIR="%REACTOS_BUILD_TOOLS_DIR%" %REACTOS_SOURCE_DIR% ) cd.. @@ -178,10 +151,6 @@ cd.. echo Configure script complete! Enter directories and execute appropriate build commands(ex: make, nmake, jom, etc...). exit /b -:fail -echo Error: Unable to detect build environment. Configure script failure. -exit /b - :cmake_notfound echo Unable to find cmake, if it is installed, check your PATH variable. exit /b diff --git a/configure.sh b/configure.sh index f513358a2a9..8aea7b9298a 100755 --- a/configure.sh +++ b/configure.sh @@ -37,7 +37,7 @@ then rm -f CMakeCache.txt fi -cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain-gcc.cmake -DARCH=$ARCH -DREACTOS_BUILD_TOOLS_DIR="$REACTOS_BUILD_TOOLS_DIR" "$REACTOS_SOURCE_DIR" +cmake -G "Unix Makefiles" -DENABLE_CCACHE=0 -DPCH=0 -DCMAKE_TOOLCHAIN_FILE=toolchain-gcc.cmake -DARCH=$ARCH -DREACTOS_BUILD_TOOLS_DIR="$REACTOS_BUILD_TOOLS_DIR" "$REACTOS_SOURCE_DIR" echo Configure script complete! Enter directories and execute appropriate build commands\(ex: make, makex, etc...\). diff --git a/dll/3rdparty/libxslt/CMakeLists.txt b/dll/3rdparty/libxslt/CMakeLists.txt index 882cef34c3e..10df37c5b02 100644 --- a/dll/3rdparty/libxslt/CMakeLists.txt +++ b/dll/3rdparty/libxslt/CMakeLists.txt @@ -1,4 +1,6 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + add_definitions( -DHAVE_CONFIG_H -DWIN32 @@ -40,4 +42,5 @@ if(MSVC) endif() add_dependencies(libxslt psdk) +add_pch(libxslt libxslt.h) add_cd_file(TARGET libxslt DESTINATION reactos/system32 FOR all) diff --git a/dll/3rdparty/mesa32/CMakeLists.txt b/dll/3rdparty/mesa32/CMakeLists.txt index c69a6cbfeae..978f8910bee 100644 --- a/dll/3rdparty/mesa32/CMakeLists.txt +++ b/dll/3rdparty/mesa32/CMakeLists.txt @@ -259,7 +259,7 @@ else() endif() add_library(mesa32 SHARED ${SOURCE}) - +add_pch(mesa32 src/main/glheader.h) set_entrypoint(mesa32 0) add_importlibs(mesa32 gdi32 user32 msvcrt kernel32 ntdll) add_dependencies(mesa32 psdk) diff --git a/dll/CMakeLists.txt b/dll/CMakeLists.txt index 77a2635c05c..dfba1ee53fd 100644 --- a/dll/CMakeLists.txt +++ b/dll/CMakeLists.txt @@ -3,7 +3,6 @@ add_subdirectory(3rdparty) add_subdirectory(cpl) add_subdirectory(directx) add_subdirectory(keyboard) -add_subdirectory(nls) add_subdirectory(ntdll) add_subdirectory(shellext) add_subdirectory(win32) diff --git a/dll/cpl/access/CMakeLists.txt b/dll/cpl/access/CMakeLists.txt index 6ee6db7d6e7..6c78ce27997 100644 --- a/dll/cpl/access/CMakeLists.txt +++ b/dll/cpl/access/CMakeLists.txt @@ -24,4 +24,5 @@ add_importlibs(access comctl32 kernel32) +add_pch(access access.h) add_cd_file(TARGET access DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/access/access.c b/dll/cpl/access/access.c index a2dd9b3befd..7b0a85eb160 100644 --- a/dll/cpl/access/access.c +++ b/dll/cpl/access/access.c @@ -8,12 +8,6 @@ * Copyright 2007 Eric Kohl */ -#include -#include -#include -#include -#include -#include "resource.h" #include "access.h" #define NUM_APPLETS (1) diff --git a/dll/cpl/access/access.h b/dll/cpl/access/access.h index 88c29d2c8c7..5237cb947b6 100644 --- a/dll/cpl/access/access.h +++ b/dll/cpl/access/access.h @@ -1,4 +1,12 @@ -#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" typedef LONG (CALLBACK *APPLET_INITPROC)(VOID); diff --git a/dll/cpl/access/display.c b/dll/cpl/access/display.c index 7924a5842f5..cf09292b118 100644 --- a/dll/cpl/access/display.c +++ b/dll/cpl/access/display.c @@ -8,12 +8,6 @@ * Copyright 2007 Eric Kohl */ -#include -#include -#include -#include -#include -#include "resource.h" #include "access.h" diff --git a/dll/cpl/access/general.c b/dll/cpl/access/general.c index b55cea6a0c8..7fb7cf93770 100644 --- a/dll/cpl/access/general.c +++ b/dll/cpl/access/general.c @@ -8,13 +8,6 @@ * Copyright 2007 Eric Kohl */ -#include -#include -#include -#include -#include -#include -#include "resource.h" #include "access.h" diff --git a/dll/cpl/access/keyboard.c b/dll/cpl/access/keyboard.c index 90451eadb8f..1b2f3081eeb 100644 --- a/dll/cpl/access/keyboard.c +++ b/dll/cpl/access/keyboard.c @@ -8,13 +8,6 @@ * Copyright 2007 Eric Kohl */ -#include -#include -#include -#include -#include -#include -#include "resource.h" #include "access.h" diff --git a/dll/cpl/access/mouse.c b/dll/cpl/access/mouse.c index d5109b00f23..0fe19e5b6a1 100644 --- a/dll/cpl/access/mouse.c +++ b/dll/cpl/access/mouse.c @@ -8,12 +8,6 @@ * Copyright 2007 Eric Kohl */ -#include -#include -#include -#include -#include -#include "resource.h" #include "access.h" diff --git a/dll/cpl/access/sound.c b/dll/cpl/access/sound.c index 9dd1636b065..9190189ece4 100644 --- a/dll/cpl/access/sound.c +++ b/dll/cpl/access/sound.c @@ -8,11 +8,6 @@ * Copyright 2007 Eric Kohl */ -#include -#include -#include -#include -#include "resource.h" #include "access.h" diff --git a/dll/cpl/appwiz/CMakeLists.txt b/dll/cpl/appwiz/CMakeLists.txt index cf5b76fa428..a5be5f13620 100644 --- a/dll/cpl/appwiz/CMakeLists.txt +++ b/dll/cpl/appwiz/CMakeLists.txt @@ -23,4 +23,5 @@ add_importlibs(appwiz shell32 kernel32) +add_pch(appwiz appwiz.h) add_cd_file(TARGET appwiz DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/appwiz/appwiz.h b/dll/cpl/appwiz/appwiz.h index 8ee2bd4c6b3..355cffc86a1 100644 --- a/dll/cpl/appwiz/appwiz.h +++ b/dll/cpl/appwiz/appwiz.h @@ -1,5 +1,3 @@ -#pragma once - #define COBJMACROS #include #include diff --git a/dll/cpl/desk/CMakeLists.txt b/dll/cpl/desk/CMakeLists.txt index d7d8d8214a7..fe5c1876b20 100644 --- a/dll/cpl/desk/CMakeLists.txt +++ b/dll/cpl/desk/CMakeLists.txt @@ -45,4 +45,5 @@ add_importlibs(desk kernel32 ntdll) +add_pch(desk desk.h) add_cd_file(TARGET desk DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/desk/advappdlg.c b/dll/cpl/desk/advappdlg.c index 837adcf2d73..3742534ee11 100644 --- a/dll/cpl/desk/advappdlg.c +++ b/dll/cpl/desk/advappdlg.c @@ -10,9 +10,6 @@ */ #include "desk.h" -#include "theme.h" -#include "appearance.h" -#include "preview.h" /******************************************************************************/ diff --git a/dll/cpl/desk/appearance.c b/dll/cpl/desk/appearance.c index 7670f4c9e00..1711ab0f779 100644 --- a/dll/cpl/desk/appearance.c +++ b/dll/cpl/desk/appearance.c @@ -9,9 +9,6 @@ */ #include "desk.h" -#include "theme.h" -#include "preview.h" -#include "appearance.h" /******************************************************************************/ diff --git a/dll/cpl/desk/desk.c b/dll/cpl/desk/desk.c index bb31e511956..cd229010a19 100644 --- a/dll/cpl/desk/desk.c +++ b/dll/cpl/desk/desk.c @@ -9,7 +9,6 @@ */ #include "desk.h" -#include "preview.h" #define NUM_APPLETS (1) diff --git a/dll/cpl/desk/desk.h b/dll/cpl/desk/desk.h index f1ac24de143..5ed0ed9efd7 100644 --- a/dll/cpl/desk/desk.h +++ b/dll/cpl/desk/desk.h @@ -1,5 +1,3 @@ -#pragma once - #define COBJMACROS #include #include @@ -12,6 +10,13 @@ #include #include #include +#include + +#include "theme.h" +#include "appearance.h" +#include "preview.h" +#include "draw.h" +#include "monslctl.h" #include "resource.h" diff --git a/dll/cpl/desk/devsett.c b/dll/cpl/desk/devsett.c index d175d1a9a6d..0bac48b5128 100644 --- a/dll/cpl/desk/devsett.c +++ b/dll/cpl/desk/devsett.c @@ -7,8 +7,6 @@ #include "desk.h" -#include - #define NDEBUG #include diff --git a/dll/cpl/desk/draw.c b/dll/cpl/desk/draw.c index 982ac9c1401..8107b245f15 100644 --- a/dll/cpl/desk/draw.c +++ b/dll/cpl/desk/draw.c @@ -8,8 +8,6 @@ */ #include "desk.h" -#include "theme.h" -#include "draw.h" #define MENU_BAR_ITEMS_SPACE (12) diff --git a/dll/cpl/desk/effappdlg.c b/dll/cpl/desk/effappdlg.c index 910c5d3b395..4e2cfe826d1 100644 --- a/dll/cpl/desk/effappdlg.c +++ b/dll/cpl/desk/effappdlg.c @@ -9,8 +9,6 @@ */ #include "desk.h" -#include "theme.h" -#include "appearance.h" /* Update all the controls with the current values for the selected screen element */ static VOID diff --git a/dll/cpl/desk/monslctl.c b/dll/cpl/desk/monslctl.c index 74390fcb717..0a15cf8f231 100644 --- a/dll/cpl/desk/monslctl.c +++ b/dll/cpl/desk/monslctl.c @@ -1,7 +1,5 @@ -#include -#include -#include -#include "monslctl.h" + +#include "desk.h" static const TCHAR szMonitorSelWndClass[] = TEXT("MONITORSELWNDCLASS"); diff --git a/dll/cpl/desk/preview.c b/dll/cpl/desk/preview.c index c6e6a3210b5..09513bb2115 100644 --- a/dll/cpl/desk/preview.c +++ b/dll/cpl/desk/preview.c @@ -7,9 +7,6 @@ */ #include "desk.h" -#include "theme.h" -#include "preview.h" -#include "draw.h" static const TCHAR szPreviewWndClass[] = TEXT("PreviewWndClass"); diff --git a/dll/cpl/desk/settings.c b/dll/cpl/desk/settings.c index cc6fb974f88..d9527cf239b 100644 --- a/dll/cpl/desk/settings.c +++ b/dll/cpl/desk/settings.c @@ -9,7 +9,6 @@ */ #include "desk.h" -#include "monslctl.h" typedef struct _DATA { diff --git a/dll/cpl/desk/theme.c b/dll/cpl/desk/theme.c index 821206fab2e..c4e2fe3ebac 100644 --- a/dll/cpl/desk/theme.c +++ b/dll/cpl/desk/theme.c @@ -8,7 +8,6 @@ */ #include "desk.h" -#include "theme.h" static BOOL g_PresetLoaded = FALSE; static INT g_TemplateCount = 0; @@ -24,7 +23,7 @@ static const TCHAR g_SelectedStyle[] = TEXT("SelectedStyle"); THEME_PRESET g_ThemeTemplates[MAX_TEMPLATES]; /* This is the list of names for the colors stored in the registry */ -const TCHAR g_RegColorNames[NUM_COLORS][MAX_COLORNAMELENGTH] = +static const TCHAR *g_RegColorNames[NUM_COLORS] = {TEXT("Scrollbar"), /* 00 = COLOR_SCROLLBAR */ TEXT("Background"), /* 01 = COLOR_DESKTOP */ TEXT("ActiveTitle"), /* 02 = COLOR_ACTIVECAPTION */ @@ -59,11 +58,11 @@ const TCHAR g_RegColorNames[NUM_COLORS][MAX_COLORNAMELENGTH] = }; /* This is the list of used metrics and their numbers */ -const int g_SizeMetric[NUM_SIZES] = +static const int g_SizeMetric[NUM_SIZES] = { SM_CXBORDER, /* 00: SIZE_BORDER_X */ SM_CYBORDER, /* 01: SIZE_BORDER_Y */ - SM_CYCAPTION, /* 02: SIZE_CAPTION_Y */ + SM_CYSIZE, /* 02: SIZE_CAPTION_Y */ SM_CXICON, /* 03: SIZE_ICON_X */ SM_CYICON, /* 04: SIZE_ICON_Y */ SM_CXICONSPACING, /* 05: SIZE_ICON_SPC_X */ @@ -72,7 +71,7 @@ const int g_SizeMetric[NUM_SIZES] = SM_CYMENU, /* 08: SIZE_MENU_Y */ SM_CXVSCROLL, /* 09: SIZE_SCROLL_X */ SM_CYHSCROLL, /* 10: SIZE_SCROLL_Y */ - SM_CYSMCAPTION, /* 11: SIZE_SMCAPTION_Y */ + SM_CYSMSIZE, /* 11: SIZE_SMCAPTION_Y */ SM_CXEDGE, /* 12: SIZE_EDGE_X */ SM_CYEDGE, /* 13: SIZE_EDGE_Y */ SM_CYSIZEFRAME, /* 14: SIZE_FRAME_Y */ @@ -120,8 +119,8 @@ VOID LoadCurrentTheme(THEME* theme) /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings * Just keep them in sync for now: */ - theme->Effects.bTooltipAnimation = theme->Effects.bMenuAnimation; - theme->Effects.bTooltipFade = theme->Effects.bMenuFade; + theme->Effects.bTooltipAnimation = theme->Effects.bMenuAnimation; + theme->Effects.bTooltipFade = theme->Effects.bMenuFade; /* show content of windows during dragging */ SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &theme->Effects.bDragFullWindows, 0); @@ -134,10 +133,11 @@ BOOL LoadThemeFromReg(THEME* theme, INT ThemeId) { INT i; TCHAR strSelectedStyle[4]; - TCHAR strSizeName[20] = {TEXT("Sizes\\0")}; + TCHAR strSizeName[20] = TEXT("Sizes\\0"); TCHAR strValueName[10]; HKEY hkNewSchemes, hkScheme, hkSize; DWORD dwType, dwLength; + UINT64 iSize; BOOL Ret = FALSE; if (!g_PresetLoaded) @@ -191,12 +191,14 @@ BOOL LoadThemeFromReg(THEME* theme, INT ThemeId) { wsprintf(strValueName, TEXT("Size #%d"), i); dwLength = sizeof(UINT64); - if (RegQueryValueEx(hkSize, strValueName, NULL, &dwType, (LPBYTE)&theme->Size[i], &dwLength) != ERROR_SUCCESS || + if (RegQueryValueEx(hkSize, strValueName, NULL, &dwType, (LPBYTE)&iSize, &dwLength) != ERROR_SUCCESS || dwType != REG_QWORD || dwLength != sizeof(UINT64)) { /* Failed to read registry value, initialize with current setting for now */ theme->Size[i] = GetSystemMetrics(g_SizeMetric[i]); } + else + theme->Size[i] = (INT)iSize; } RegCloseKey(hkScheme); } @@ -208,18 +210,10 @@ BOOL LoadThemeFromReg(THEME* theme, INT ThemeId) return Ret; } -static VOID -_UpdateUserPref(UINT SpiGet, UINT SpiSet, BOOL *pbFlag) -{ - SystemParametersInfo(SpiSet, 0, (PVOID)pbFlag, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); -} -#define UPDATE_USERPREF(NAME,pbFlag) _UpdateUserPref(SPI_GET ## NAME, SPI_SET ## NAME, pbFlag) - VOID ApplyTheme(THEME* theme, INT ThemeId) { INT i, Result; HKEY hKey; - DWORD dwDisposition; TCHAR clText[16]; NONCLIENTMETRICS NonClientMetrics; ICONMETRICS IconMetrics; @@ -228,13 +222,7 @@ VOID ApplyTheme(THEME* theme, INT ThemeId) SetSysColors(NUM_COLORS, g_ColorList, theme->crColor); /* Save colors to registry */ - Result = RegOpenKeyEx(HKEY_CURRENT_USER, g_CPColors, 0, KEY_ALL_ACCESS, &hKey); - if (Result != ERROR_SUCCESS) - { - /* Could not open the key, try to create it */ - Result = RegCreateKeyEx(HKEY_CURRENT_USER, g_CPColors, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); - } - + Result = RegCreateKeyEx(HKEY_CURRENT_USER, g_CPColors, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); if (Result == ERROR_SUCCESS) { for (i = 0; i < NUM_COLORS; i++) @@ -289,19 +277,19 @@ VOID ApplyTheme(THEME* theme, INT ThemeId) theme->Effects.bTooltipFade = theme->Effects.bMenuFade; SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, theme->Effects.bDragFullWindows, (PVOID)&theme->Effects.bDragFullWindows, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); SystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(theme->Effects.bKeyboardCues), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); - //UPDATE_USERPREF(ACTIVEWINDOWTRACKING, &theme->Effects.bActiveWindowTracking); - //UPDATE_USERPREF(MENUANIMATION, &theme->Effects.bMenuAnimation); - //UPDATE_USERPREF(COMBOBOXANIMATION, &theme->Effects.bComboBoxAnimation); - //UPDATE_USERPREF(LISTBOXSMOOTHSCROLLING, &theme->Effects.bListBoxSmoothScrolling); - //UPDATE_USERPREF(GRADIENTCAPTIONS, &theme->Effects.bGradientCaptions); - //UPDATE_USERPREF(ACTIVEWNDTRKZORDER, &theme->Effects.bActiveWndTrkZorder); - //UPDATE_USERPREF(HOTTRACKING, &theme->Effects.bHotTracking); - UPDATE_USERPREF(MENUFADE, &theme->Effects.bMenuFade); - //UPDATE_USERPREF(SELECTIONFADE, &theme->Effects.bSelectionFade); - UPDATE_USERPREF(TOOLTIPANIMATION, &theme->Effects.bTooltipAnimation); - UPDATE_USERPREF(TOOLTIPFADE, &theme->Effects.bTooltipFade); - //UPDATE_USERPREF(CURSORSHADOW, &theme->Effects.bCursorShadow); - //UPDATE_USERPREF(UIEFFECTS, &theme->Effects.bUiEffects); + //SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)&theme->Effects.bActiveWindowTracking, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETMENUANIMATION, 0, (PVOID)&theme->Effects.bMenuAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETCOMBOBOXANIMATION, 0, (PVOID)&theme->Effects.bComboBoxAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (PVOID)&theme->Effects.bListBoxSmoothScrolling, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETGRADIENTCAPTIONS, 0, (PVOID)&theme->Effects.bGradientCaptions, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)&theme->Effects.bActiveWndTrkZorder, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETHOTTRACKING, 0, (PVOID)&theme->Effects.bHotTracking, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + SystemParametersInfo(SPI_SETMENUFADE, 0, (PVOID)&theme->Effects.bMenuFade, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETSELECTIONFADE, 0, (PVOID)&theme->Effects.bSelectionFade, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + SystemParametersInfo(SPI_SETTOOLTIPANIMATION, 0, (PVOID)&theme->Effects.bTooltipAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + SystemParametersInfo(SPI_SETTOOLTIPFADE, 0, (PVOID)&theme->Effects.bTooltipFade, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)&theme->Effects.bCursorShadow, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); + //SystemParametersInfo(SPI_SETUIEFFECTS, 0, (PVOID)&theme->Effects.bUiEffects, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE); /* Save ThemeId */ Result = RegOpenKeyEx(HKEY_CURRENT_USER, g_CPANewSchemes, 0, KEY_ALL_ACCESS, &hKey); diff --git a/dll/cpl/desk/theme.h b/dll/cpl/desk/theme.h index 7c72c98193a..68a7a253da2 100644 --- a/dll/cpl/desk/theme.h +++ b/dll/cpl/desk/theme.h @@ -33,7 +33,6 @@ #define NUM_SIZES 20 #define NUM_COLORS 31 #define MAX_TEMPLATES 50 -#define MAX_COLORNAMELENGTH 30 #define MAX_TEMPLATENAMELENTGH 80 /* Some typedefs for theme */ @@ -77,8 +76,6 @@ typedef struct TCHAR strLegacyName[MAX_TEMPLATENAMELENTGH]; } THEME_PRESET; -extern const TCHAR g_RegColorNames[NUM_COLORS][MAX_COLORNAMELENGTH]; -extern const INT g_SizeMetric[NUM_SIZES]; extern THEME_PRESET g_ThemeTemplates[MAX_TEMPLATES]; /* prototypes for theme.c */ diff --git a/dll/cpl/inetcpl/inetcpl.rc b/dll/cpl/inetcpl/inetcpl.rc index 48b23738ed5..e7a2c8d0da4 100644 --- a/dll/cpl/inetcpl/inetcpl.rc +++ b/dll/cpl/inetcpl/inetcpl.rc @@ -30,6 +30,7 @@ #include "lang/ko-KR.rc" #include "lang/lt-LT.rc" #include "lang/nl-NL.rc" +#include "lang/pl-PL.rc" #include "lang/pt-PT.rc" #include "lang/ru-RU.rc" #include "lang/Sr.rc" diff --git a/dll/cpl/inetcpl/lang/pl-PL.rc b/dll/cpl/inetcpl/lang/pl-PL.rc index 42f4f38eaea..d3dd98224aa 100644 --- a/dll/cpl/inetcpl/lang/pl-PL.rc +++ b/dll/cpl/inetcpl/lang/pl-PL.rc @@ -1,7 +1,7 @@ /* * Internet control panel applet * - * Copyright 2010 £ukasz Wojni³owicz + * Copyright 2010 Łukasz Wojniłowicz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,24 +23,27 @@ LANGUAGE LANG_POLISH, SUBLANG_DEFAULT +/* UTF-8 */ +#pragma code_page(65001) + /* "General" propsheet */ IDD_GENERAL DIALOG 0, 0, 320, 220 STYLE WS_CAPTION | WS_CHILD | WS_DISABLED FONT 8, "MS Shell Dlg" -CAPTION "Ogólne" +CAPTION "Ogólne" BEGIN GROUPBOX " Strona domowa ", IDC_STATIC, 4, 4, 312, 52 - LTEXT "Mo¿esz wybraæ adres strony, która bêdzie twoj¹ stron¹ domow¹.", + LTEXT "Możesz wybrać adres strony, która będzie twoją stroną domową.", IDC_STATIC, 58, 10, 252, 10 EDITTEXT IDC_HOME_EDIT, 58, 22, 252, 12, WS_VISIBLE | ES_AUTOHSCROLL - PUSHBUTTON "U¿yj &bie¿¹cej", IDC_HOME_CURRENT, 58, 36, 80, 14 - PUSHBUTTON "U¿yj d&omyœlnej", IDC_HOME_DEFAULT, 144, 36, 80, 14 - PUSHBUTTON "U¿yj pu&stej", IDC_HOME_BLANK, 230, 36, 80, 14 - GROUPBOX " Historia przegl¹dania ", IDC_STATIC, 4, 60, 312, 46 - LTEXT "Mo¿esz usun¹æ przechowywane strony, ciasteczka i inne dane.", + PUSHBUTTON "Użyj &bieżącej", IDC_HOME_CURRENT, 58, 36, 80, 14 + PUSHBUTTON "Użyj d&omyślnej", IDC_HOME_DEFAULT, 144, 36, 80, 14 + PUSHBUTTON "Użyj pu&stej", IDC_HOME_BLANK, 230, 36, 80, 14 + GROUPBOX " Historia przeglądania ", IDC_STATIC, 4, 60, 312, 46 + LTEXT "Możesz usunąć przechowywane strony, ciasteczka i inne dane.", IDC_STATIC, 58, 72, 252, 10 - PUSHBUTTON "&Usuñ pliki...", IDC_HISTORY_DELETE, 144, 86, 80, 14 + PUSHBUTTON "&Usuń pliki...", IDC_HISTORY_DELETE, 144, 86, 80, 14 PUSHBUTTON "Ustawie&nia...", IDC_HISTORY_SETTINGS, 230, 86, 80, 14 END @@ -49,33 +52,51 @@ END IDD_DELETE_HISTORY DIALOG 0, 0, 250, 250 STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU FONT 8, "MS Shell Dlg" -CAPTION "Usuwanie historii przegl¹dania" +CAPTION "Usuwanie historii przeglądania" BEGIN - AUTOCHECKBOX "Tymczasowe pliki internetowe\nKopie stron sieci Web, obrazów i certyfikatów.", + AUTOCHECKBOX "Tymczasowe pliki internetowe\nKopie stron sieci Web, obrazów i certyfikatów.", IDC_DELETE_TEMP_FILES, 10, 8, 230, 30, BS_TOP | BS_MULTILINE AUTOCHECKBOX "Pliki cookies\nPliki przechowywane na komputerze przez witryny sieci Web w celu zapisania preferencji takich jak informacje logowania.", IDC_DELETE_COOKIES, 10, 38, 230, 30, BS_TOP | BS_MULTILINE AUTOCHECKBOX "Historia\nLista odwiedzonych witryn sieci Web.", IDC_DELETE_HISTORY, 10, 68, 230, 30, BS_TOP | BS_MULTILINE - AUTOCHECKBOX "Dane formularzy\nZapisane informacje, które zosta³y wpisane w formularzach.", + AUTOCHECKBOX "Dane formularzy\nZapisane informacje, które zostały wpisane w formularzach.", IDC_DELETE_FORM_DATA, 10, 98, 230, 30, BS_TOP | BS_MULTILINE - AUTOCHECKBOX "Has³a\nHas³a uzupe³niane automatycznie po zalogowaniu siê do wczeœniej odwiedzonej witryny Web.", + AUTOCHECKBOX "Hasła\nHasła uzupełniane automatycznie po zalogowaniu się do wcześniej odwiedzonej witryny Web.", IDC_DELETE_PASSWORDS, 10, 128, 230, 30, BS_TOP | BS_MULTILINE DEFPUSHBUTTON "Anuluj", IDCANCEL, 185, 230, 60, 15, WS_GROUP - PUSHBUTTON "Usuñ", IDOK, 120, 230, 60, 15, WS_GROUP + PUSHBUTTON "Usuń", IDOK, 120, 230, 60, 15, WS_GROUP + +END + +/* "Security" propsheet */ +IDD_SECURITY DIALOG 0, 0, 320, 220 +STYLE WS_CAPTION | WS_CHILD | WS_DISABLED +FONT 8, "MS Shell Dlg" +CAPTION "Bezpieczeństwo" +BEGIN + CONTROL "Listview", IDC_SEC_LISTVIEW, "SysListView32", + LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | WS_VSCROLL, + 4, 4, 312, 58 + LTEXT "", IDC_SEC_ZONE_INFO, 4, 68, 312, 20 + GROUPBOX "", IDC_SEC_GROUP, 4, 88, 312, 126 + CONTROL "trackbar", IDC_SEC_TRACKBAR, "msctls_trackbar32", + TBS_VERT | TBS_AUTOTICKS | TBS_BOTH | TBS_REVERSED, 8, 98, 32, 100 + LTEXT "", IDC_SEC_LEVEL, 48, 102, 180, 12 + LTEXT "", IDC_SEC_LEVEL_INFO, 48, 114, 260, 80 END /* "Content" propsheet */ IDD_CONTENT DIALOG 0, 0, 320, 220 STYLE WS_CAPTION | WS_CHILD | WS_DISABLED FONT 8, "MS Shell Dlg" -CAPTION "Zawartoœæ" +CAPTION "Zawartość" BEGIN GROUPBOX " Certyfikaty ", IDC_STATIC, 4, 4, 312, 50 - LTEXT "Certyfikaty s¹ u¿ywane do twojej osobistej identyfikacji oraz do identyfikacji wydawców i urzêdów certyfikuj¹cych.", + LTEXT "Certyfikaty są używane do twojej osobistej identyfikacji oraz do identyfikacji wydawców i urzędów certyfikujących.", IDC_STATIC, 58, 14, 252, 18 PUSHBUTTON "Certyfikaty...", IDC_CERT, 146, 34, 80, 14 PUSHBUTTON "Wydawcy...", IDC_CERT_PUBLISHER, 230, 34, 80, 14 diff --git a/dll/cpl/input/CMakeLists.txt b/dll/cpl/input/CMakeLists.txt index f6da9712807..6b86afe2d92 100644 --- a/dll/cpl/input/CMakeLists.txt +++ b/dll/cpl/input/CMakeLists.txt @@ -23,4 +23,5 @@ add_importlibs(input gdi32 kernel32) +add_pch(input input.h) add_cd_file(TARGET input DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/input/changekeyseq.c b/dll/cpl/input/changekeyseq.c index ac06de7e8d7..e38cbff7b93 100644 --- a/dll/cpl/input/changekeyseq.c +++ b/dll/cpl/input/changekeyseq.c @@ -8,7 +8,6 @@ * 06-09-2007 Created */ -#include "resource.h" #include "input.h" BOOL diff --git a/dll/cpl/input/input.c b/dll/cpl/input/input.c index 558bff4bfcc..d3548ce8103 100644 --- a/dll/cpl/input/input.c +++ b/dll/cpl/input/input.c @@ -9,7 +9,6 @@ * 06-09-2007 Created */ -#include "resource.h" #include "input.h" #define NUM_APPLETS (1) diff --git a/dll/cpl/input/input.h b/dll/cpl/input/input.h index dcf0ac7d5e5..84655831819 100644 --- a/dll/cpl/input/input.h +++ b/dll/cpl/input/input.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include @@ -10,6 +8,8 @@ #include #include +#include "resource.h" + typedef LONG (CALLBACK *CPLAPPLET_PROC)(VOID); typedef struct diff --git a/dll/cpl/input/keysettings.c b/dll/cpl/input/keysettings.c index d66676c181b..56a5254d283 100644 --- a/dll/cpl/input/keysettings.c +++ b/dll/cpl/input/keysettings.c @@ -9,7 +9,6 @@ * 06-09-2007 Created */ -#include "resource.h" #include "input.h" static HWND hKeySettingsWnd; diff --git a/dll/cpl/input/settings.c b/dll/cpl/input/settings.c index 5f1ca81e066..849d70cd62a 100644 --- a/dll/cpl/input/settings.c +++ b/dll/cpl/input/settings.c @@ -10,7 +10,6 @@ * 06-09-2007 Created */ -#include "resource.h" #include "input.h" static HWND MainDlgWnd; diff --git a/dll/cpl/intl/CMakeLists.txt b/dll/cpl/intl/CMakeLists.txt index a1f1aa5ab29..7af2bd2f7f0 100644 --- a/dll/cpl/intl/CMakeLists.txt +++ b/dll/cpl/intl/CMakeLists.txt @@ -30,4 +30,5 @@ add_importlibs(intl shell32 kernel32) +add_pch(intl intl.h) add_cd_file(TARGET intl DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/intl/advanced.c b/dll/cpl/intl/advanced.c index 2196e762552..22c5a11bfc4 100644 --- a/dll/cpl/intl/advanced.c +++ b/dll/cpl/intl/advanced.c @@ -1,13 +1,5 @@ -#include -#include -#include -#include -#include -#include -#include #include "intl.h" -#include "resource.h" typedef struct CPStruct { diff --git a/dll/cpl/intl/currency.c b/dll/cpl/intl/currency.c index b355640a6da..74df951da19 100644 --- a/dll/cpl/intl/currency.c +++ b/dll/cpl/intl/currency.c @@ -24,13 +24,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" #define POSITIVE_EXAMPLE _T("123456789.00") #define NEGATIVE_EXAMPLE _T("-123456789.00") diff --git a/dll/cpl/intl/date.c b/dll/cpl/intl/date.c index b92d4c2d66b..ff7468f870a 100644 --- a/dll/cpl/intl/date.c +++ b/dll/cpl/intl/date.c @@ -24,13 +24,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" /* GLOBALS ******************************************************************/ diff --git a/dll/cpl/intl/generalp.c b/dll/cpl/intl/generalp.c index f1e93241449..9cbe5d032b1 100644 --- a/dll/cpl/intl/generalp.c +++ b/dll/cpl/intl/generalp.c @@ -26,13 +26,7 @@ * Aleksey Bragin */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" #define SAMPLE_NUMBER _T("123456789") #define NO_FLAG 0 diff --git a/dll/cpl/intl/inplocale.c b/dll/cpl/intl/inplocale.c index e80e1f996ed..785cf902aaa 100644 --- a/dll/cpl/intl/inplocale.c +++ b/dll/cpl/intl/inplocale.c @@ -24,14 +24,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" - /* Property page dialog callback */ INT_PTR CALLBACK diff --git a/dll/cpl/intl/intl.c b/dll/cpl/intl/intl.c index 1f084950e8a..d3dc375a306 100644 --- a/dll/cpl/intl/intl.c +++ b/dll/cpl/intl/intl.c @@ -23,15 +23,8 @@ * PURPOSE: Property sheet code * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include -#include #include "intl.h" -#include "resource.h" - #define NUM_APPLETS (1) diff --git a/dll/cpl/intl/intl.h b/dll/cpl/intl/intl.h index 12de475dc5e..20dbbba4ff1 100644 --- a/dll/cpl/intl/intl.h +++ b/dll/cpl/intl/intl.h @@ -1,6 +1,14 @@ -#pragma once - +#include #include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" #define DECIMAL_RADIX 10 diff --git a/dll/cpl/intl/kblayouts.c b/dll/cpl/intl/kblayouts.c index 34335b96e6d..d1a8f982ab5 100644 --- a/dll/cpl/intl/kblayouts.c +++ b/dll/cpl/intl/kblayouts.c @@ -5,13 +5,7 @@ * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" /* Character Count of a layout ID like "00000409" */ #define CCH_LAYOUT_ID 8 diff --git a/dll/cpl/intl/languages.c b/dll/cpl/intl/languages.c index 17dba22f605..1ae36d94870 100644 --- a/dll/cpl/intl/languages.c +++ b/dll/cpl/intl/languages.c @@ -1,10 +1,5 @@ -#include -#include -#include -#include #include "intl.h" -#include "resource.h" /* Property page dialog callback */ INT_PTR CALLBACK diff --git a/dll/cpl/intl/misc.c b/dll/cpl/intl/misc.c index 7a9be0e3e3d..bd5d5dec7c8 100644 --- a/dll/cpl/intl/misc.c +++ b/dll/cpl/intl/misc.c @@ -1,10 +1,5 @@ -#include -#include -#include -#include #include "intl.h" -#include "resource.h" #define NUM_SHEETS 4 diff --git a/dll/cpl/intl/numbers.c b/dll/cpl/intl/numbers.c index 75f609bda1d..3169879fae8 100644 --- a/dll/cpl/intl/numbers.c +++ b/dll/cpl/intl/numbers.c @@ -24,13 +24,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" #define SAMPLE_NUMBER _T("123456789") #define SAMPLE_NEG_NUMBER _T("-123456789") diff --git a/dll/cpl/intl/setupreg.c b/dll/cpl/intl/setupreg.c index ae85e94c948..b9c464b2b6a 100644 --- a/dll/cpl/intl/setupreg.c +++ b/dll/cpl/intl/setupreg.c @@ -8,13 +8,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" /* GLOBALS ******************************************************************/ diff --git a/dll/cpl/intl/sort.c b/dll/cpl/intl/sort.c index aec36951105..dc99a40fe7a 100644 --- a/dll/cpl/intl/sort.c +++ b/dll/cpl/intl/sort.c @@ -6,13 +6,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" static BOOL bSortPage = FALSE; static LCID userLcid; diff --git a/dll/cpl/intl/time.c b/dll/cpl/intl/time.c index ca21d692991..7156363813c 100644 --- a/dll/cpl/intl/time.c +++ b/dll/cpl/intl/time.c @@ -23,14 +23,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include -#include - #include "intl.h" -#include "resource.h" static HWND hwndEnum = NULL; diff --git a/dll/cpl/main/CMakeLists.txt b/dll/cpl/main/CMakeLists.txt index e193a61032f..1187ad31124 100644 --- a/dll/cpl/main/CMakeLists.txt +++ b/dll/cpl/main/CMakeLists.txt @@ -24,4 +24,5 @@ add_importlibs(main gdi32 kernel32) +add_pch(main main.h) add_cd_file(TARGET main DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/main/keyboard.c b/dll/cpl/main/keyboard.c index 293ace41805..958f5eb0ef6 100644 --- a/dll/cpl/main/keyboard.c +++ b/dll/cpl/main/keyboard.c @@ -24,16 +24,7 @@ * PROGRAMMER: Eric Kohl */ -#include -#include -#include -#include -#include -#include -#include - #include "main.h" -#include "resource.h" #define ID_BLINK_TIMER 345 diff --git a/dll/cpl/main/main.c b/dll/cpl/main/main.c index 3c259fece9e..379ab8985ea 100644 --- a/dll/cpl/main/main.c +++ b/dll/cpl/main/main.c @@ -25,16 +25,8 @@ * UPDATE HISTORY: * 05-01-2004 Created */ -#include -#include -#include -#include -#include -#include #include "main.h" -#include "resource.h" - #define NUM_APPLETS (2) diff --git a/dll/cpl/main/main.h b/dll/cpl/main/main.h index 2c32c7e63b1..50f5206c766 100644 --- a/dll/cpl/main/main.h +++ b/dll/cpl/main/main.h @@ -1,4 +1,19 @@ -#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" typedef enum { diff --git a/dll/cpl/main/mouse.c b/dll/cpl/main/mouse.c index c208fb2a5d0..a015793add0 100644 --- a/dll/cpl/main/mouse.c +++ b/dll/cpl/main/mouse.c @@ -28,22 +28,7 @@ //TODO: // add missing icons -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - #include "main.h" -#include "resource.h" #define DEFAULT_DOUBLE_CLICK_SPEED 500 #define DEFAULT_CLICK_LOCK_TIME 2200 diff --git a/dll/cpl/mmsys/CMakeLists.txt b/dll/cpl/mmsys/CMakeLists.txt index 5206561480f..62d6a5ec381 100644 --- a/dll/cpl/mmsys/CMakeLists.txt +++ b/dll/cpl/mmsys/CMakeLists.txt @@ -29,4 +29,5 @@ add_importlibs(mmsys ntdll kernel32) +add_pch(mmsys mmsys.h) add_cd_file(TARGET mmsys DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/mmsys/audio.c b/dll/cpl/mmsys/audio.c index 129004987ba..775d94282e0 100644 --- a/dll/cpl/mmsys/audio.c +++ b/dll/cpl/mmsys/audio.c @@ -8,14 +8,7 @@ * Dmitry Chapyshev */ -#include -#include -#include -#include -#include #include "mmsys.h" -#include "resource.h" - VOID InitAudioDlg(HWND hwnd) diff --git a/dll/cpl/mmsys/mmsys.c b/dll/cpl/mmsys/mmsys.c index 6e765608f5d..9b32a7ef04a 100644 --- a/dll/cpl/mmsys/mmsys.c +++ b/dll/cpl/mmsys/mmsys.c @@ -9,19 +9,7 @@ * 2005/11/23 Created */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "mmsys.h" -#include "resource.h" typedef enum { diff --git a/dll/cpl/mmsys/mmsys.h b/dll/cpl/mmsys/mmsys.h index ed6c480a0c0..f5085cc5714 100644 --- a/dll/cpl/mmsys/mmsys.h +++ b/dll/cpl/mmsys/mmsys.h @@ -1,4 +1,16 @@ -#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" //typedef LONG (CALLBACK *APPLET_PROC)(VOID); diff --git a/dll/cpl/mmsys/sounds.c b/dll/cpl/mmsys/sounds.c index c7ff17187a5..48ba4f4cdeb 100644 --- a/dll/cpl/mmsys/sounds.c +++ b/dll/cpl/mmsys/sounds.c @@ -8,15 +8,7 @@ * Dmitry Chapyshev */ -#include -#include -#include -#include -#include -#include #include "mmsys.h" -#include "resource.h" -#include struct __APP_MAP__; diff --git a/dll/cpl/mmsys/voice.c b/dll/cpl/mmsys/voice.c index ac5c4497111..f19fe69438c 100644 --- a/dll/cpl/mmsys/voice.c +++ b/dll/cpl/mmsys/voice.c @@ -8,13 +8,7 @@ * Dmitry Chapyshev */ -#include -#include -#include -#include -#include #include "mmsys.h" -#include "resource.h" /* Voice property page dialog callback */ INT_PTR CALLBACK diff --git a/dll/cpl/mmsys/volume.c b/dll/cpl/mmsys/volume.c index 19f518bccea..836b13d4596 100644 --- a/dll/cpl/mmsys/volume.c +++ b/dll/cpl/mmsys/volume.c @@ -8,14 +8,7 @@ * Dmitry Chapyshev */ -#include -#include -#include -#include -#include -#include #include "mmsys.h" -#include "resource.h" #define VOLUME_DIVIDER 0xFFF diff --git a/dll/cpl/powercfg/CMakeLists.txt b/dll/cpl/powercfg/CMakeLists.txt index c0beaa6ecef..f449a940347 100644 --- a/dll/cpl/powercfg/CMakeLists.txt +++ b/dll/cpl/powercfg/CMakeLists.txt @@ -25,4 +25,5 @@ add_importlibs(powercfg kernel32 ntdll) +add_pch(powercfg powercfg.h) add_cd_file(TARGET powercfg DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/powercfg/advanced.c b/dll/cpl/powercfg/advanced.c index 20c4b85fe07..15313f259c4 100644 --- a/dll/cpl/powercfg/advanced.c +++ b/dll/cpl/powercfg/advanced.c @@ -14,12 +14,6 @@ //typedef long NTSTATUS; //#endif -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include -#include -#include -#include "resource.h" #include "powercfg.h" HWND hAdv = 0; diff --git a/dll/cpl/powercfg/alarms.c b/dll/cpl/powercfg/alarms.c index 464723b0858..df44386c416 100644 --- a/dll/cpl/powercfg/alarms.c +++ b/dll/cpl/powercfg/alarms.c @@ -10,14 +10,6 @@ * Dmitry Chapyshev (lentind@yandex.ru) */ - -#include -#include -#include -#include -#include - -#include "resource.h" #include "powercfg.h" static BOOLEAN diff --git a/dll/cpl/powercfg/hibernate.c b/dll/cpl/powercfg/hibernate.c index 77cc51d441f..1b69cc8c95b 100644 --- a/dll/cpl/powercfg/hibernate.c +++ b/dll/cpl/powercfg/hibernate.c @@ -14,18 +14,8 @@ //typedef long NTSTATUS; //#endif -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include -#include -#include -#include -#include - -#include "resource.h" #include "powercfg.h" - BOOLEAN Pos_InitData(); void Adv_InitDialog(); diff --git a/dll/cpl/powercfg/powercfg.c b/dll/cpl/powercfg/powercfg.c index af764b2a17b..28c7b84f5a0 100644 --- a/dll/cpl/powercfg/powercfg.c +++ b/dll/cpl/powercfg/powercfg.c @@ -10,13 +10,6 @@ * Dmitry Chapyshev (lentind@yandex.ru) */ -#include -#include -#include -#include -#include - -#include "resource.h" #include "powercfg.h" #define NUM_APPLETS (1) diff --git a/dll/cpl/powercfg/powercfg.h b/dll/cpl/powercfg/powercfg.h index 27b54e596a8..c5997889204 100644 --- a/dll/cpl/powercfg/powercfg.h +++ b/dll/cpl/powercfg/powercfg.h @@ -1,6 +1,16 @@ -#pragma once +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include + +#include +#include +#include +#include +#include +#include #include "powrprof.h" +#include "resource.h" typedef struct { diff --git a/dll/cpl/powercfg/powershemes.c b/dll/cpl/powercfg/powershemes.c index cf8ced7e80b..05037de508c 100644 --- a/dll/cpl/powercfg/powershemes.c +++ b/dll/cpl/powercfg/powershemes.c @@ -10,13 +10,7 @@ * Dmitry Chapyshev (lentind@yandex.ru) */ -#include -#include -#include -#include -#include "resource.h" #include "powercfg.h" -#include "stdio.h" UINT Sec[]= { diff --git a/dll/cpl/timedate/CMakeLists.txt b/dll/cpl/timedate/CMakeLists.txt index 9dbc98ee293..32727d391ce 100644 --- a/dll/cpl/timedate/CMakeLists.txt +++ b/dll/cpl/timedate/CMakeLists.txt @@ -27,4 +27,5 @@ add_importlibs(timedate msvcrt kernel32) +add_pch(timedate timedate.h) add_cd_file(TARGET timedate DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/timedate/timedate.h b/dll/cpl/timedate/timedate.h index ced96a12eec..97e6acb09ae 100644 --- a/dll/cpl/timedate/timedate.h +++ b/dll/cpl/timedate/timedate.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/dll/cpl/usrmgr/CMakeLists.txt b/dll/cpl/usrmgr/CMakeLists.txt index a1d0ec5e12a..1449fa7db7e 100644 --- a/dll/cpl/usrmgr/CMakeLists.txt +++ b/dll/cpl/usrmgr/CMakeLists.txt @@ -30,5 +30,5 @@ add_importlibs(usrmgr kernel32 ntdll) - +add_pch(usrmgr usrmgr.h) add_cd_file(TARGET usrmgr DESTINATION reactos/system32 FOR all) diff --git a/dll/cpl/usrmgr/usrmgr.h b/dll/cpl/usrmgr/usrmgr.h index 13896cd147c..1a6fdf84338 100644 --- a/dll/cpl/usrmgr/usrmgr.h +++ b/dll/cpl/usrmgr/usrmgr.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/dll/directx/devenum/CMakeLists.txt b/dll/directx/devenum/CMakeLists.txt index c31eefaaf50..b023838734f 100644 --- a/dll/directx/devenum/CMakeLists.txt +++ b/dll/directx/devenum/CMakeLists.txt @@ -35,4 +35,5 @@ add_importlibs(devenum kernel32 ntdll) +add_pch(devenum devenum_private.h) add_cd_file(TARGET devenum DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/dmusic/CMakeLists.txt b/dll/directx/dmusic/CMakeLists.txt index df15dcf81f4..29bc7d43c05 100644 --- a/dll/directx/dmusic/CMakeLists.txt +++ b/dll/directx/dmusic/CMakeLists.txt @@ -40,5 +40,5 @@ add_importlibs(dmusic ntdll) add_dependencies(dmusic psdk) - +add_pch(dmusic dmusic_private.h) add_cd_file(TARGET dmusic DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/dxdiagn/CMakeLists.txt b/dll/directx/dxdiagn/CMakeLists.txt index 59b0dc31d47..e736f2705a9 100644 --- a/dll/directx/dxdiagn/CMakeLists.txt +++ b/dll/directx/dxdiagn/CMakeLists.txt @@ -25,4 +25,5 @@ add_importlibs(dxdiagn kernel32 ntdll) +add_pch(dxdiagn dxdiag_private.h) add_cd_file(TARGET dxdiagn DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/qedit/CMakeLists.txt b/dll/directx/qedit/CMakeLists.txt index b088850deb6..1f411e334b2 100644 --- a/dll/directx/qedit/CMakeLists.txt +++ b/dll/directx/qedit/CMakeLists.txt @@ -32,5 +32,6 @@ add_importlibs(qedit kernel32 ntdll) +add_pch(qedit qedit_private.h) add_dependencies(qedit dxsdk) add_cd_file(TARGET qedit DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/quartz/CMakeLists.txt b/dll/directx/quartz/CMakeLists.txt index 338fd2e5a97..aff19556112 100644 --- a/dll/directx/quartz/CMakeLists.txt +++ b/dll/directx/quartz/CMakeLists.txt @@ -70,4 +70,5 @@ add_importlibs(quartz kernel32 ntdll) +add_pch(quartz quartz_private.h) add_cd_file(TARGET quartz DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/wine/d3d8/CMakeLists.txt b/dll/directx/wine/d3d8/CMakeLists.txt index 5586bd68c78..495823691d2 100644 --- a/dll/directx/wine/d3d8/CMakeLists.txt +++ b/dll/directx/wine/d3d8/CMakeLists.txt @@ -43,4 +43,5 @@ add_importlibs(d3d8 ntdll) add_dependencies(d3d8 wineheaders) +add_pch(d3d8 d3d8_private.h) add_cd_file(TARGET d3d8 DESTINATION reactos/system32 FOR all) diff --git a/dll/directx/wine/d3d9/CMakeLists.txt b/dll/directx/wine/d3d9/CMakeLists.txt index 642815dc02b..172149ffcf0 100644 --- a/dll/directx/wine/d3d9/CMakeLists.txt +++ b/dll/directx/wine/d3d9/CMakeLists.txt @@ -46,5 +46,6 @@ add_importlibs(d3d9 ntdll) add_dependencies(d3d9 wineheaders) +add_pch(d3d9 d3d9_private.h) add_cd_file(TARGET d3d9 DESTINATION reactos/system32 FOR all) add_importlib_target(d3d9.spec) diff --git a/dll/directx/wine/d3dx9_24/CMakeLists.txt b/dll/directx/wine/d3dx9_24/CMakeLists.txt index 39ce0ce0371..5ad6cb35f9e 100644 --- a/dll/directx/wine/d3dx9_24/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_24/CMakeLists.txt @@ -24,7 +24,6 @@ add_importlibs(d3dx9_24 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_25/CMakeLists.txt b/dll/directx/wine/d3dx9_25/CMakeLists.txt index 98c9a7f9e79..c7b5b2c2a61 100644 --- a/dll/directx/wine/d3dx9_25/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_25/CMakeLists.txt @@ -25,7 +25,6 @@ add_importlibs(d3dx9_25 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_26/CMakeLists.txt b/dll/directx/wine/d3dx9_26/CMakeLists.txt index 82f45db4c0e..efb2eeb47a2 100644 --- a/dll/directx/wine/d3dx9_26/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_26/CMakeLists.txt @@ -25,7 +25,6 @@ add_importlibs(d3dx9_26 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_27/CMakeLists.txt b/dll/directx/wine/d3dx9_27/CMakeLists.txt index 595fb303814..974974657cc 100644 --- a/dll/directx/wine/d3dx9_27/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_27/CMakeLists.txt @@ -25,7 +25,6 @@ add_importlibs(d3dx9_27 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_28/CMakeLists.txt b/dll/directx/wine/d3dx9_28/CMakeLists.txt index 1abdaf0b692..5d34deb88b8 100644 --- a/dll/directx/wine/d3dx9_28/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_28/CMakeLists.txt @@ -25,7 +25,6 @@ add_importlibs(d3dx9_28 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_29/CMakeLists.txt b/dll/directx/wine/d3dx9_29/CMakeLists.txt index 431a7830835..e0d576f3b1f 100644 --- a/dll/directx/wine/d3dx9_29/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_29/CMakeLists.txt @@ -25,7 +25,6 @@ add_importlibs(d3dx9_29 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_30/CMakeLists.txt b/dll/directx/wine/d3dx9_30/CMakeLists.txt index d6d00c81cf3..00ce311e881 100644 --- a/dll/directx/wine/d3dx9_30/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_30/CMakeLists.txt @@ -25,7 +25,6 @@ add_importlibs(d3dx9_30 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_31/CMakeLists.txt b/dll/directx/wine/d3dx9_31/CMakeLists.txt index aa45584de71..84ad7f4bff5 100644 --- a/dll/directx/wine/d3dx9_31/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_31/CMakeLists.txt @@ -24,7 +24,6 @@ add_importlibs(d3dx9_31 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_32/CMakeLists.txt b/dll/directx/wine/d3dx9_32/CMakeLists.txt index 249e8195303..2daf736e121 100644 --- a/dll/directx/wine/d3dx9_32/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_32/CMakeLists.txt @@ -24,7 +24,6 @@ add_importlibs(d3dx9_32 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_33/CMakeLists.txt b/dll/directx/wine/d3dx9_33/CMakeLists.txt index cefe373c27c..be87694c231 100644 --- a/dll/directx/wine/d3dx9_33/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_33/CMakeLists.txt @@ -24,7 +24,6 @@ add_importlibs(d3dx9_33 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_34/CMakeLists.txt b/dll/directx/wine/d3dx9_34/CMakeLists.txt index 7353481b206..80ae9093171 100644 --- a/dll/directx/wine/d3dx9_34/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_34/CMakeLists.txt @@ -24,7 +24,6 @@ add_importlibs(d3dx9_34 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_35/CMakeLists.txt b/dll/directx/wine/d3dx9_35/CMakeLists.txt index 361ffa4671e..f71621388ab 100644 --- a/dll/directx/wine/d3dx9_35/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_35/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_35 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_36/CMakeLists.txt b/dll/directx/wine/d3dx9_36/CMakeLists.txt index 34ca20bf6a6..1d5c48876a9 100644 --- a/dll/directx/wine/d3dx9_36/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_36/CMakeLists.txt @@ -32,7 +32,6 @@ add_importlibs(d3dx9_36 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_37/CMakeLists.txt b/dll/directx/wine/d3dx9_37/CMakeLists.txt index cd49aee8e97..ac929e8263d 100644 --- a/dll/directx/wine/d3dx9_37/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_37/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_37 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_38/CMakeLists.txt b/dll/directx/wine/d3dx9_38/CMakeLists.txt index a5d8f25ac4a..9fccb7207cd 100644 --- a/dll/directx/wine/d3dx9_38/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_38/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_38 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_39/CMakeLists.txt b/dll/directx/wine/d3dx9_39/CMakeLists.txt index 84597ea257c..668b18dc006 100644 --- a/dll/directx/wine/d3dx9_39/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_39/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_39 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_40/CMakeLists.txt b/dll/directx/wine/d3dx9_40/CMakeLists.txt index c9cfe0ae082..7c80c06f2cf 100644 --- a/dll/directx/wine/d3dx9_40/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_40/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_40 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_41/CMakeLists.txt b/dll/directx/wine/d3dx9_41/CMakeLists.txt index e8fbf0eeee0..4a6b5d5d73a 100644 --- a/dll/directx/wine/d3dx9_41/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_41/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_41 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/d3dx9_42/CMakeLists.txt b/dll/directx/wine/d3dx9_42/CMakeLists.txt index 75ee61b765d..0bcaa8ccb37 100644 --- a/dll/directx/wine/d3dx9_42/CMakeLists.txt +++ b/dll/directx/wine/d3dx9_42/CMakeLists.txt @@ -23,7 +23,6 @@ add_importlibs(d3dx9_42 user32 gdi32 advapi32 - wined3d msvcrt kernel32 ntdll) diff --git a/dll/directx/wine/ddraw/CMakeLists.txt b/dll/directx/wine/ddraw/CMakeLists.txt index b05d1a50343..042f2b11647 100644 --- a/dll/directx/wine/ddraw/CMakeLists.txt +++ b/dll/directx/wine/ddraw/CMakeLists.txt @@ -52,5 +52,6 @@ add_importlibs(ddraw ntdll) add_dependencies(ddraw wineheaders) +add_pch(ddraw ddraw_private.h) add_cd_file(TARGET ddraw DESTINATION reactos/system32 FOR all) add_importlib_target(ddraw.spec) diff --git a/dll/directx/wine/wined3d/CMakeLists.txt b/dll/directx/wine/wined3d/CMakeLists.txt index 01989775c42..a7b742b28ed 100644 --- a/dll/directx/wine/wined3d/CMakeLists.txt +++ b/dll/directx/wine/wined3d/CMakeLists.txt @@ -67,5 +67,6 @@ add_importlibs(wined3d ntdll) add_dependencies(wined3d wineheaders) +add_pch(wined3d wined3d_private.h) add_cd_file(TARGET wined3d DESTINATION reactos/system32 FOR all) add_importlib_target(wined3d.spec) diff --git a/dll/nls/CMakeLists.txt b/dll/nls/CMakeLists.txt index be0dd91e913..d6448d3ad32 100644 --- a/dll/nls/CMakeLists.txt +++ b/dll/nls/CMakeLists.txt @@ -2,4 +2,4 @@ if(NOT MSVC) add_subdirectory(idndl) # FIXME: msvc build. endif() -add_subdirectory(normaliz) +#add_subdirectory(normaliz) # Win Vista diff --git a/dll/ntdll/CMakeLists.txt b/dll/ntdll/CMakeLists.txt index a2b2c9da239..9fd4bab21ea 100644 --- a/dll/ntdll/CMakeLists.txt +++ b/dll/ntdll/CMakeLists.txt @@ -15,13 +15,10 @@ list(APPEND SOURCE csr/capture.c csr/connect.c dbg/dbgui.c - ldr/actctx.c ldr/ldrapi.c ldr/ldrinit.c ldr/ldrpe.c ldr/ldrutils.c - ldr/startup.c - ldr/utils.c rtl/libsupp.c rtl/version.c def/ntdll.rc @@ -43,6 +40,7 @@ set_entrypoint(ntdll 0) if(MSVC) target_link_libraries(ntdll rtl) +add_linkerflag(ntdll /RELEASE) else() target_link_libraries(ntdll -Wl,--whole-archive rtl -Wl,--no-whole-archive) endif() diff --git a/dll/ntdll/def/ntdll.spec b/dll/ntdll/def/ntdll.spec index b1805ae7f3d..891306e5ad3 100644 --- a/dll/ntdll/def/ntdll.spec +++ b/dll/ntdll/def/ntdll.spec @@ -411,6 +411,7 @@ ;@ stdcall RtlAbortRXact @ stdcall RtlAbsoluteToSelfRelativeSD(ptr ptr ptr) @ stdcall RtlAcquirePebLock() +@ stdcall RtlAcquirePrivilege(ptr long long ptr) @ stdcall RtlAcquireResourceExclusive(ptr long) @ stdcall RtlAcquireResourceShared(ptr long) @ stdcall RtlAcquireSRWLockExclusive(ptr) @@ -723,7 +724,7 @@ @ stdcall RtlInt64ToUnicodeString(double long ptr) @ stdcall RtlIntegerToChar(long long long ptr) @ stdcall RtlIntegerToUnicodeString(long long ptr) -;@ stdcall RtlInterlockedCompareExchange64 +@ stdcall -arch=win32 -ret64 RtlInterlockedCompareExchange64(ptr double double) @ stdcall -arch=i386,x86_64 RtlInterlockedFlushSList(ptr) @ stdcall -arch=i386,x86_64 RtlInterlockedPopEntrySList(ptr) @ stdcall -arch=i386,x86_64 RtlInterlockedPushEntrySList(ptr ptr) @@ -846,6 +847,7 @@ @ stdcall RtlReleaseActivationContext(ptr) ;@ stdcall RtlReleaseMemoryStream @ stdcall RtlReleasePebLock() +@ stdcall RtlReleasePrivilege(ptr) @ stdcall RtlReleaseResource(ptr) @ stdcall RtlReleaseSRWLockExclusive(ptr) @ stdcall RtlReleaseSRWLockShared(ptr) diff --git a/dll/ntdll/dispatch/amd64/stubs.c b/dll/ntdll/dispatch/amd64/stubs.c index fe7b4a78656..f8c836496f1 100644 --- a/dll/ntdll/dispatch/amd64/stubs.c +++ b/dll/ntdll/dispatch/amd64/stubs.c @@ -41,3 +41,27 @@ KiUserApcDispatcher(IN PVOID NormalRoutine, UNIMPLEMENTED; return; } + +VOID +NTAPI +KiRaiseUserExceptionDispatcher() +{ + UNIMPLEMENTED; + return; +} + +VOID +NTAPI +KiUserCallbackDispatcher() +{ + UNIMPLEMENTED; + return; +} + +VOID +NTAPI +KiUserExceptionDispatcher() +{ + UNIMPLEMENTED; + return; +} diff --git a/dll/ntdll/dispatch/i386/dispatch.S b/dll/ntdll/dispatch/i386/dispatch.S index 25f7c34bcee..10706e21827 100644 --- a/dll/ntdll/dispatch/i386/dispatch.S +++ b/dll/ntdll/dispatch/i386/dispatch.S @@ -184,7 +184,8 @@ _KiRaiseUserExceptionDispatcher@0: PUBLIC _KiUserExceptionDispatcher@8 -_KiUserExceptionDispatcher@8: +.PROC KiUserExceptionDispatcher@8 + FPO 0, 0, 0, 0, 0, FRAME_FPO /* Clear direction flag */ cld @@ -240,9 +241,11 @@ Exit: call _RtlRaiseException@4 ret 8 +.ENDP KiUserExceptionDispatcher@8 PUBLIC _KiIntSystemCall@0 -_KiIntSystemCall@0: +.PROC KiIntSystemCall@0 + FPO 0, 0, 0, 0, 0, FRAME_FPO /* Set stack in EDX and do the interrupt */ lea edx, [esp+8] @@ -251,21 +254,26 @@ _KiIntSystemCall@0: /* Return to caller */ ret +.ENDP KiIntSystemCall@0 PUBLIC _KiFastSystemCall@0 -_KiFastSystemCall@0: +.PROC KiFastSystemCall@0 + FPO 0, 0, 0, 0, 0, FRAME_FPO /* Put ESP in EDX and do the SYSENTER */ mov edx, esp sysenter +.ENDP KiFastSystemCall@0 PUBLIC _KiFastSystemCallRet@0 -_KiFastSystemCallRet@0: +.PROC KiFastSystemCallRet@0 + FPO 0, 0, 0, 0, 0, FRAME_FPO /* Just return to caller */ ret +.ENDP KiFastSystemCallRet@0 PUBLIC _RtlpGetStackLimits@8 _RtlpGetStackLimits@8: diff --git a/dll/ntdll/include/ntdllp.h b/dll/ntdll/include/ntdllp.h index dc4bf7593ba..e343e8fd304 100644 --- a/dll/ntdll/include/ntdllp.h +++ b/dll/ntdll/include/ntdllp.h @@ -9,23 +9,23 @@ /* INCLUDES ******************************************************************/ #define LDR_HASH_TABLE_ENTRIES 32 +#define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1)) /* LdrpUpdateLoadCount2 flags */ #define LDRP_UPDATE_REFCOUNT 0x01 #define LDRP_UPDATE_DEREFCOUNT 0x02 #define LDRP_UPDATE_PIN 0x03 +/* Loader flags */ +#define IMAGE_LOADER_FLAGS_COMPLUS 0x00000001 +#define IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL 0x01000000 + typedef struct _LDRP_TLS_DATA { LIST_ENTRY TlsLinks; IMAGE_TLS_DIRECTORY TlsDirectory; } LDRP_TLS_DATA, *PLDRP_TLS_DATA; -typedef BOOL -(NTAPI *PDLLMAIN_FUNC)(HANDLE hInst, - ULONG ul_reason_for_call, - LPVOID lpReserved); - /* Global data */ extern RTL_CRITICAL_SECTION LdrpLoaderLock; extern BOOLEAN LdrpInLdrInit; @@ -42,7 +42,7 @@ extern BOOLEAN LdrpLdrDatabaseIsSetup; extern ULONG LdrpActiveUnloadCount; extern BOOLEAN LdrpShutdownInProgress; extern UNICODE_STRING LdrpKnownDllPath; -extern PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache; +extern PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache, LdrpLoadedDllHandleCache; /* ldrinit.c */ NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL); @@ -50,8 +50,8 @@ VOID NTAPI LdrpInitializeThread(IN PCONTEXT Context); NTSTATUS NTAPI LdrpInitializeTls(VOID); NTSTATUS NTAPI LdrpAllocateTls(VOID); VOID NTAPI LdrpFreeTls(VOID); -VOID NTAPI LdrpTlsCallback(PVOID BaseAddress, ULONG Reason); -BOOLEAN NTAPI LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context); +VOID NTAPI LdrpCallTlsInitializers(PVOID BaseAddress, ULONG Reason); +BOOLEAN NTAPI LdrpCallInitRoutine(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context); NTSTATUS NTAPI LdrpInitializeProcess(PCONTEXT Context, PVOID SystemArgument1); VOID NTAPI LdrpInitFailure(NTSTATUS Status); VOID NTAPI LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry); @@ -102,6 +102,16 @@ LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry, ULONG NTAPI LdrpClearLoadInProgress(); +NTSTATUS +NTAPI +LdrpSetProtection(PVOID ViewBase, + BOOLEAN Restore); + +BOOLEAN +NTAPI +LdrpCheckForLoadedDllHandle(IN PVOID Base, + OUT PLDR_DATA_TABLE_ENTRY *LdrEntry); + BOOLEAN NTAPI LdrpCheckForLoadedDll(IN PWSTR DllPath, IN PUNICODE_STRING DllName, @@ -121,7 +131,7 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL, PVOID NTAPI LdrpFetchAddressOfEntryPoint(PVOID ImageBase); -BOOLEAN NTAPI +VOID NTAPI LdrpFreeUnicodeString(PUNICODE_STRING String); @@ -136,6 +146,18 @@ NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle, ULONG LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders); +NTSTATUS +NTAPI +LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, + IN LPSTR ImportName, + IN PVOID DllBase, + OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry, + OUT PBOOLEAN Existing); + +VOID +NTAPI +LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry); + extern HANDLE WindowsApiPort; /* EOF */ diff --git a/dll/ntdll/ldr/actctx.c b/dll/ntdll/ldr/actctx.c deleted file mode 100644 index c859e6bc7ce..00000000000 --- a/dll/ntdll/ldr/actctx.c +++ /dev/null @@ -1,91 +0,0 @@ - -#include -#define NDEBUG -#include - -#include "wine/unicode.h" - - -/*********************************************************************** - * create_module_activation_context - */ -NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module ) -{ - NTSTATUS status; - LDR_RESOURCE_INFO info; - IMAGE_RESOURCE_DATA_ENTRY *entry; - - info.Type = (ULONG)RT_MANIFEST; - info.Name = (ULONG)ISOLATIONAWARE_MANIFEST_RESOURCE_ID; - info.Language = 0; - if (!(status = LdrFindResource_U( module->DllBase, &info, 3, &entry ))) - { - ACTCTXW ctx; - ctx.cbSize = sizeof(ctx); - ctx.lpSource = NULL; - ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; - ctx.hModule = module->DllBase; - ctx.lpResourceName = (LPCWSTR)ISOLATIONAWARE_MANIFEST_RESOURCE_ID; - status = RtlCreateActivationContext( &module->EntryPointActivationContext, &ctx ); - } - return status; -} - -NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fullname ) -{ - static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\',0}; - /* FIXME: Handle modules that have a private manifest file - static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; */ - - ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; - ACTCTX_SECTION_KEYED_DATA data; - UNICODE_STRING nameW; - NTSTATUS status; - SIZE_T needed, size = 1024; - - RtlInitUnicodeString( &nameW, libname ); - data.cbSize = sizeof(data); - status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, - ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, - &nameW, &data ); - if (status != STATUS_SUCCESS) return status; - - for (;;) - { - if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) - { - status = STATUS_NO_MEMORY; - goto done; - } - status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex, - AssemblyDetailedInformationInActivationContext, - info, size, &needed ); - if (status == STATUS_SUCCESS) break; - if (status != STATUS_BUFFER_TOO_SMALL) goto done; - RtlFreeHeap( RtlGetProcessHeap(), 0, info ); - size = needed; - } - - DPRINT("manafestpath === %S\n", info->lpAssemblyManifestPath); - DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName); - if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName) - { - status = STATUS_SXS_KEY_NOT_FOUND; - goto done; - } - - DPRINT("%S. %S\n", info->lpAssemblyManifestPath, info->lpAssemblyDirectoryName); - wcscpy(fullname , SharedUserData->NtSystemRoot); - wcscat(fullname, winsxsW); - wcscat(fullname, info->lpAssemblyDirectoryName); - wcscat(fullname, L"\\"); - wcscat(fullname, libname); - DPRINT("Successfully found a side by side %S\n", fullname); - status = STATUS_SUCCESS; - -done: - RtlFreeHeap( RtlGetProcessHeap(), 0, info ); - RtlReleaseActivationContext( data.hActCtx ); - DPRINT("%S\n", fullname); - return status; -} diff --git a/dll/ntdll/ldr/elf.c b/dll/ntdll/ldr/elf.c deleted file mode 100644 index ecc82ce0c5d..00000000000 --- a/dll/ntdll/ldr/elf.c +++ /dev/null @@ -1,2824 +0,0 @@ -/* - * REACTOS ELF LOADER - * - * ELF run-time linker, ported from FreeBSD by KJK::Hyperion as part of the ELF - * support initiative. Original copyright, licensing and disclaimers follow - */ - -/*- - * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. - * Copyright 2003 Alexander Kabaev . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/rtld.c,v 1.101 2004/11/02 09:42:21 ssouhlal Exp $ - */ - - -/* - * Dynamic linker for ELF. - * - * John Polstra . - */ - -#include -#define NDEBUG -#include - -#if 0 - -#ifndef __GNUC__ -#error "GCC is needed to compile this file" -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "rtld.h" -#include "libmap.h" -#include "rtld_tls.h" - -#ifndef COMPAT_32BIT -#define PATH_RTLD "/libexec/ld-elf.so.1" -#else -#define PATH_RTLD "/libexec/ld-elf32.so.1" -#endif - -/* Types. */ -typedef void (*func_ptr_type)(); -typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); - -/* - * This structure provides a reentrant way to keep a list of objects and - * check which ones have already been processed in some way. - */ -typedef struct Struct_DoneList { - const Obj_Entry **objs; /* Array of object pointers */ - unsigned int num_alloc; /* Allocated size of the array */ - unsigned int num_used; /* Number of array slots used */ -} DoneList; - -/* - * Function declarations. - */ -static const char *basename(const char *); -static void die(void); -static void digest_dynamic(Obj_Entry *, int); -static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); -static Obj_Entry *dlcheck(void *); -static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); -static bool donelist_check(DoneList *, const Obj_Entry *); -static void errmsg_restore(char *); -static char *errmsg_save(void); -static void *fill_search_info(const char *, size_t, void *); -static char *find_library(const char *, const Obj_Entry *); -static const char *gethints(void); -static void init_dag(Obj_Entry *); -static void init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *); -static void init_rtld(caddr_t); -static void initlist_add_neededs(Needed_Entry *needed, Objlist *list); -static void initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, - Objlist *list); -static bool is_exported(const Elf_Sym *); -static void linkmap_add(Obj_Entry *); -static void linkmap_delete(Obj_Entry *); -static int load_needed_objects(Obj_Entry *); -static int load_preload_objects(void); -static Obj_Entry *load_object(char *); -static Obj_Entry *obj_from_addr(const void *); -static void objlist_call_fini(Objlist *); -static void objlist_call_init(Objlist *); -static void objlist_clear(Objlist *); -static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); -static void objlist_init(Objlist *); -static void objlist_push_head(Objlist *, Obj_Entry *); -static void objlist_push_tail(Objlist *, Obj_Entry *); -static void objlist_remove(Objlist *, Obj_Entry *); -static void objlist_remove_unref(Objlist *); -static void *path_enumerate(const char *, path_enum_proc, void *); -static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); -static int rtld_dirname(const char *, char *); -static void rtld_exit(void); -static char *search_library_path(const char *, const char *); -static const void **get_program_var_addr(const char *name); -static void set_program_var(const char *, const void *); -static const Elf_Sym *symlook_default(const char *, unsigned long hash, - const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt); -static const Elf_Sym *symlook_list(const char *, unsigned long, - Objlist *, const Obj_Entry **, bool in_plt, DoneList *); -static void trace_loaded_objects(Obj_Entry *obj); -static void unlink_object(Obj_Entry *); -static void unload_object(Obj_Entry *); -static void unref_dag(Obj_Entry *); -static void ref_dag(Obj_Entry *); - -void r_debug_state(struct r_debug*, struct link_map*); - -/* - * Data declarations. - */ -static char *error_message; /* Message for dlerror(), or NULL */ -struct r_debug r_debug; /* for GDB; */ -static bool libmap_disable; /* Disable libmap */ -static bool trust; /* False for setuid and setgid programs */ -static char *ld_bind_now; /* Environment variable for immediate binding */ -static char *ld_debug; /* Environment variable for debugging */ -static char *ld_library_path; /* Environment variable for search path */ -static char *ld_preload; /* Environment variable for libraries to - load first */ -static char *ld_tracing; /* Called from ldd to print libs */ -static Obj_Entry *obj_list; /* Head of linked list of shared objects */ -static Obj_Entry **obj_tail; /* Link field of last object in list */ -static Obj_Entry *obj_main; /* The main program shared object */ -static Obj_Entry obj_rtld; /* The dynamic linker shared object */ -static unsigned int obj_count; /* Number of objects in obj_list */ - -static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ - STAILQ_HEAD_INITIALIZER(list_global); -static Objlist list_main = /* Objects loaded at program startup */ - STAILQ_HEAD_INITIALIZER(list_main); -static Objlist list_fini = /* Objects needing fini() calls */ - STAILQ_HEAD_INITIALIZER(list_fini); - -static Elf_Sym sym_zero; /* For resolving undefined weak refs. */ - -#define GDB_STATE(s,m) r_debug.r_state = s; r_debug_state(&r_debug,m); - -extern Elf_Dyn _DYNAMIC; -#pragma weak _DYNAMIC -#ifndef RTLD_IS_DYNAMIC -#define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) -#endif - -/* - * These are the functions the dynamic linker exports to application - * programs. They are the only symbols the dynamic linker is willing - * to export from itself. - */ -static func_ptr_type exports[] = { - (func_ptr_type) &_rtld_error, - (func_ptr_type) &dlclose, - (func_ptr_type) &dlerror, - (func_ptr_type) &dlopen, - (func_ptr_type) &dlsym, - (func_ptr_type) &dladdr, - (func_ptr_type) &dllockinit, - (func_ptr_type) &dlinfo, - (func_ptr_type) &_rtld_thread_init, -#ifdef __i386__ - (func_ptr_type) &___tls_get_addr, -#endif - (func_ptr_type) &__tls_get_addr, - (func_ptr_type) &_rtld_allocate_tls, - (func_ptr_type) &_rtld_free_tls, - NULL -}; - -/* - * Global declarations normally provided by crt1. The dynamic linker is - * not built with crt1, so we have to provide them ourselves. - */ -char *__progname; -char **environ; - -/* - * Globals to control TLS allocation. - */ -size_t tls_last_offset; /* Static TLS offset of last module */ -size_t tls_last_size; /* Static TLS size of last module */ -size_t tls_static_space; /* Static TLS space allocated */ -int tls_dtv_generation = 1; /* Used to detect when dtv size changes */ -int tls_max_index = 1; /* Largest module index allocated */ - -/* - * Fill in a DoneList with an allocation large enough to hold all of - * the currently-loaded objects. Keep this as a macro since it calls - * alloca and we want that to occur within the scope of the caller. - */ -#define donelist_init(dlp) \ - ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]), \ - assert((dlp)->objs != NULL), \ - (dlp)->num_alloc = obj_count, \ - (dlp)->num_used = 0) - -/* - * Main entry point for dynamic linking. The first argument is the - * stack pointer. The stack is expected to be laid out as described - * in the SVR4 ABI specification, Intel 386 Processor Supplement. - * Specifically, the stack pointer points to a word containing - * ARGC. Following that in the stack is a null-terminated sequence - * of pointers to argument strings. Then comes a null-terminated - * sequence of pointers to environment strings. Finally, there is a - * sequence of "auxiliary vector" entries. - * - * The second argument points to a place to store the dynamic linker's - * exit procedure pointer and the third to a place to store the main - * program's object. - * - * The return value is the main program's entry point. - */ -func_ptr_type -_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) -{ - Elf_Auxinfo *aux_info[AT_COUNT]; - int i; - int argc; - char **argv; - char **env; - Elf_Auxinfo *aux; - Elf_Auxinfo *auxp; - const char *argv0; - Objlist_Entry *entry; - Obj_Entry *obj; - Obj_Entry **preload_tail; - Objlist initlist; - int lockstate; - - /* - * On entry, the dynamic linker itself has not been relocated yet. - * Be very careful not to reference any global data until after - * init_rtld has returned. It is OK to reference file-scope statics - * and string constants, and to call static and global functions. - */ - - /* Find the auxiliary vector on the stack. */ - argc = *sp++; - argv = (char **) sp; - sp += argc + 1; /* Skip over arguments and NULL terminator */ - env = (char **) sp; - while (*sp++ != 0) /* Skip over environment, and NULL terminator */ - ; - aux = (Elf_Auxinfo *) sp; - - /* Digest the auxiliary vector. */ - for (i = 0; i < AT_COUNT; i++) - aux_info[i] = NULL; - for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { - if (auxp->a_type < AT_COUNT) - aux_info[auxp->a_type] = auxp; - } - - /* Initialize and relocate ourselves. */ - assert(aux_info[AT_BASE] != NULL); - init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr); - - __progname = obj_rtld.path; - argv0 = argv[0] != NULL ? argv[0] : "(null)"; - environ = env; - - trust = !issetugid(); - - ld_bind_now = getenv(LD_ "BIND_NOW"); - if (trust) { - ld_debug = getenv(LD_ "DEBUG"); - libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; - ld_library_path = getenv(LD_ "LIBRARY_PATH"); - ld_preload = getenv(LD_ "PRELOAD"); - } - ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); - - if (ld_debug != NULL && *ld_debug != '\0') - debug = 1; - dbg("%s is initialized, base address = %p", __progname, - (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); - dbg("RTLD dynamic = %p", obj_rtld.dynamic); - dbg("RTLD pltgot = %p", obj_rtld.pltgot); - - /* - * Load the main program, or process its program header if it is - * already loaded. - */ - if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ - int fd = aux_info[AT_EXECFD]->a_un.a_val; - dbg("loading main program"); - obj_main = map_object(fd, argv0, NULL); - close(fd); - if (obj_main == NULL) - die(); - } else { /* Main program already loaded. */ - const Elf_Phdr *phdr; - int phnum; - caddr_t entry; - - dbg("processing main program's program header"); - assert(aux_info[AT_PHDR] != NULL); - phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; - assert(aux_info[AT_PHNUM] != NULL); - phnum = aux_info[AT_PHNUM]->a_un.a_val; - assert(aux_info[AT_PHENT] != NULL); - assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); - assert(aux_info[AT_ENTRY] != NULL); - entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; - if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL) - die(); - } - - obj_main->path = xstrdup(argv0); - obj_main->mainprog = true; - - /* - * Get the actual dynamic linker pathname from the executable if - * possible. (It should always be possible.) That ensures that - * gdb will find the right dynamic linker even if a non-standard - * one is being used. - */ - if (obj_main->interp != NULL && - strcmp(obj_main->interp, obj_rtld.path) != 0) { - free(obj_rtld.path); - obj_rtld.path = xstrdup(obj_main->interp); - __progname = obj_rtld.path; - } - - digest_dynamic(obj_main, 0); - - linkmap_add(obj_main); - linkmap_add(&obj_rtld); - - /* Link the main program into the list of objects. */ - *obj_tail = obj_main; - obj_tail = &obj_main->next; - obj_count++; - /* Make sure we don't call the main program's init and fini functions. */ - obj_main->init = obj_main->fini = (Elf_Addr)NULL; - - /* Initialize a fake symbol for resolving undefined weak references. */ - sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); - sym_zero.st_shndx = SHN_UNDEF; - - if (!libmap_disable) - libmap_disable = (bool)lm_init(); - - dbg("loading LD_PRELOAD libraries"); - if (load_preload_objects() == -1) - die(); - preload_tail = obj_tail; - - dbg("loading needed objects"); - if (load_needed_objects(obj_main) == -1) - die(); - - /* Make a list of all objects loaded at startup. */ - for (obj = obj_list; obj != NULL; obj = obj->next) { - objlist_push_tail(&list_main, obj); - obj->refcount++; - } - - if (ld_tracing) { /* We're done */ - trace_loaded_objects(obj_main); - exit(0); - } - - if (getenv(LD_ "DUMP_REL_PRE") != NULL) { - dump_relocations(obj_main); - exit (0); - } - - /* setup TLS for main thread */ - dbg("initializing initial thread local storage"); - STAILQ_FOREACH(entry, &list_main, link) { - /* - * Allocate all the initial objects out of the static TLS - * block even if they didn't ask for it. - */ - allocate_tls_offset(entry->obj); - } - allocate_initial_tls(obj_list); - - if (relocate_objects(obj_main, - ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld) == -1) - die(); - - dbg("doing copy relocations"); - if (do_copy_relocations(obj_main) == -1) - die(); - - if (getenv(LD_ "DUMP_REL_POST") != NULL) { - dump_relocations(obj_main); - exit (0); - } - - dbg("initializing key program variables"); - set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); - set_program_var("environ", env); - - dbg("initializing thread locks"); - lockdflt_init(); - - /* Make a list of init functions to call. */ - objlist_init(&initlist); - initlist_add_objects(obj_list, preload_tail, &initlist); - - r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ - - objlist_call_init(&initlist); - lockstate = wlock_acquire(rtld_bind_lock); - objlist_clear(&initlist); - wlock_release(rtld_bind_lock, lockstate); - - dbg("transferring control to program entry point = %p", obj_main->entry); - - /* Return the exit procedure and the program entry point. */ - *exit_proc = rtld_exit; - *objp = obj_main; - return (func_ptr_type) obj_main->entry; -} - -#endif /* 0 */ - -Elf_Addr -_rtld_bind(Obj_Entry *obj, Elf_Word reloff) -{ - const Elf_Rel *rel; - const Elf_Sym *def; - const Obj_Entry *defobj; - Elf_Addr *where; - Elf_Addr target; - int lockstate; - - lockstate = rlock_acquire(rtld_bind_lock); - if (obj->pltrel) - rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); - else - rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); - - where = (Elf_Addr *) (obj->relocbase + rel->r_offset); - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL); - if (def == NULL) - die(); - - target = (Elf_Addr)(defobj->relocbase + def->st_value); - - dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", - defobj->strtab + def->st_name, basename(obj->path), - (void *)target, basename(defobj->path)); - - /* - * Write the new contents for the jmpslot. Note that depending on - * architecture, the value which we need to return back to the - * lazy binding trampoline may or may not be the target - * address. The value returned from reloc_jmpslot() is the value - * that the trampoline needs. - */ - target = reloc_jmpslot(where, target, defobj, obj, rel); - rlock_release(rtld_bind_lock, lockstate); - return target; -} - -#if 0 - -/* - * Error reporting function. Use it like printf. If formats the message - * into a buffer, and sets things up so that the next call to dlerror() - * will return the message. - */ -void -_rtld_error(const char *fmt, ...) -{ - static char buf[512]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof buf, fmt, ap); - error_message = buf; - va_end(ap); -} - -/* - * Return a dynamically-allocated copy of the current error message, if any. - */ -static char * -errmsg_save(void) -{ - return error_message == NULL ? NULL : xstrdup(error_message); -} - -/* - * Restore the current error message from a copy which was previously saved - * by errmsg_save(). The copy is freed. - */ -static void -errmsg_restore(char *saved_msg) -{ - if (saved_msg == NULL) - error_message = NULL; - else { - _rtld_error("%s", saved_msg); - free(saved_msg); - } -} - -static const char * -basename(const char *name) -{ - const char *p = strrchr(name, '/'); - return p != NULL ? p + 1 : name; -} - -static void -die(void) -{ - const char *msg = dlerror(); - - if (msg == NULL) - msg = "Fatal error"; - errx(1, "%s", msg); -} - -#endif /* 0 */ - -/* - * Process a shared object's DYNAMIC section, and save the important - * information in its Obj_Entry structure. - */ -static void -digest_dynamic(Obj_Entry *obj, int early) -{ - const Elf_Dyn *dynp; - Needed_Entry **needed_tail = &obj->needed; - const Elf_Dyn *dyn_rpath = NULL; - int plttype = DT_REL; - - obj->bind_now = false; - for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { - switch (dynp->d_tag) { - - case DT_REL: - obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_RELSZ: - obj->relsize = dynp->d_un.d_val; - break; - - case DT_RELENT: - assert(dynp->d_un.d_val == sizeof(Elf_Rel)); - break; - - case DT_JMPREL: - obj->pltrel = (const Elf_Rel *) - (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_PLTRELSZ: - obj->pltrelsize = dynp->d_un.d_val; - break; - - case DT_RELA: - obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_RELASZ: - obj->relasize = dynp->d_un.d_val; - break; - - case DT_RELAENT: - assert(dynp->d_un.d_val == sizeof(Elf_Rela)); - break; - - case DT_PLTREL: - plttype = dynp->d_un.d_val; - assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); - break; - - case DT_SYMTAB: - obj->symtab = (const Elf_Sym *) - (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_SYMENT: - assert(dynp->d_un.d_val == sizeof(Elf_Sym)); - break; - - case DT_STRTAB: - obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_STRSZ: - obj->strsize = dynp->d_un.d_val; - break; - - case DT_HASH: - { - const Elf_Hashelt *hashtab = (const Elf_Hashelt *) - (obj->relocbase + dynp->d_un.d_ptr); - obj->nbuckets = hashtab[0]; - obj->nchains = hashtab[1]; - obj->buckets = hashtab + 2; - obj->chains = obj->buckets + obj->nbuckets; - } - break; - - case DT_NEEDED: - if (!obj->rtld) { - Needed_Entry *nep = NEW(Needed_Entry); - nep->name = dynp->d_un.d_val; - nep->obj = NULL; - nep->next = NULL; - - *needed_tail = nep; - needed_tail = &nep->next; - } - break; - - case DT_PLTGOT: - obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_TEXTREL: - obj->textrel = true; - break; - - case DT_SYMBOLIC: - obj->symbolic = true; - break; - - case DT_RPATH: - case DT_RUNPATH: /* XXX: process separately */ - /* - * We have to wait until later to process this, because we - * might not have gotten the address of the string table yet. - */ - dyn_rpath = dynp; - break; - - case DT_SONAME: - /* Not used by the dynamic linker. */ - break; - - case DT_INIT: - obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_FINI: - obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_DEBUG: - /* XXX - not implemented yet */ - if (!early) - dbg("Filling in DT_DEBUG entry"); - ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug; - break; - - case DT_FLAGS: - if (dynp->d_un.d_val & DF_ORIGIN) { - obj->origin_path = xmalloc(PATH_MAX); - if (rtld_dirname(obj->path, obj->origin_path) == -1) - die(); - } - if (dynp->d_un.d_val & DF_SYMBOLIC) - obj->symbolic = true; - if (dynp->d_un.d_val & DF_TEXTREL) - obj->textrel = true; - if (dynp->d_un.d_val & DF_BIND_NOW) - obj->bind_now = true; - if (dynp->d_un.d_val & DF_STATIC_TLS) - ; - break; - - default: - if (!early) { - dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, - (long)dynp->d_tag); - } - break; - } - } - - obj->traced = false; - - if (plttype == DT_RELA) { - obj->pltrela = (const Elf_Rela *) obj->pltrel; - obj->pltrel = NULL; - obj->pltrelasize = obj->pltrelsize; - obj->pltrelsize = 0; - } - - if (dyn_rpath != NULL) - obj->rpath = obj->strtab + dyn_rpath->d_un.d_val; -} - -/* - * Process a shared object's program header. This is used only for the - * main program, when the kernel has already loaded the main program - * into memory before calling the dynamic linker. It creates and - * returns an Obj_Entry structure. - */ -static Obj_Entry * -digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) -{ - Obj_Entry *obj; - const Elf_Phdr *phlimit = phdr + phnum; - const Elf_Phdr *ph; - int nsegs = 0; - - obj = obj_new(); - for (ph = phdr; ph < phlimit; ph++) { - switch (ph->p_type) { - - case PT_PHDR: - if ((const Elf_Phdr *)ph->p_vaddr != phdr) { - _rtld_error("%s: invalid PT_PHDR", path); - return NULL; - } - obj->phdr = (const Elf_Phdr *) ph->p_vaddr; - obj->phsize = ph->p_memsz; - break; - - case PT_INTERP: - obj->interp = (const char *) ph->p_vaddr; - break; - - case PT_LOAD: - if (nsegs == 0) { /* First load segment */ - obj->vaddrbase = trunc_page(ph->p_vaddr); - obj->mapbase = (caddr_t) obj->vaddrbase; - obj->relocbase = obj->mapbase - obj->vaddrbase; - obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) - - obj->vaddrbase; - } else { /* Last load segment */ - obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) - - obj->vaddrbase; - } - nsegs++; - break; - - case PT_DYNAMIC: - obj->dynamic = (const Elf_Dyn *) ph->p_vaddr; - break; - - case PT_TLS: - obj->tlsindex = 1; - obj->tlssize = ph->p_memsz; - obj->tlsalign = ph->p_align; - obj->tlsinitsize = ph->p_filesz; - obj->tlsinit = (void*) ph->p_vaddr; - break; - } - } - if (nsegs < 1) { - _rtld_error("%s: too few PT_LOAD segments", path); - return NULL; - } - - obj->entry = entry; - return obj; -} - -#if 0 - -static Obj_Entry * -dlcheck(void *handle) -{ - Obj_Entry *obj; - - for (obj = obj_list; obj != NULL; obj = obj->next) - if (obj == (Obj_Entry *) handle) - break; - - if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) { - _rtld_error("Invalid shared object handle %p", handle); - return NULL; - } - return obj; -} - -/* - * If the given object is already in the donelist, return true. Otherwise - * add the object to the list and return false. - */ -static bool -donelist_check(DoneList *dlp, const Obj_Entry *obj) -{ - unsigned int i; - - for (i = 0; i < dlp->num_used; i++) - if (dlp->objs[i] == obj) - return true; - /* - * Our donelist allocation should always be sufficient. But if - * our threads locking isn't working properly, more shared objects - * could have been loaded since we allocated the list. That should - * never happen, but we'll handle it properly just in case it does. - */ - if (dlp->num_used < dlp->num_alloc) - dlp->objs[dlp->num_used++] = obj; - return false; -} - -#endif /* 0 */ - -/* - * Hash function for symbol table lookup. Don't even think about changing - * this. It is specified by the System V ABI. - */ -unsigned long -elf_hash(const char *name) -{ - const unsigned char *p = (const unsigned char *) name; - unsigned long h = 0; - unsigned long g; - - while (*p != '\0') { - h = (h << 4) + *p++; - if ((g = h & 0xf0000000) != 0) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -#if 0 - -/* - * Find the library with the given name, and return its full pathname. - * The returned string is dynamically allocated. Generates an error - * message and returns NULL if the library cannot be found. - * - * If the second argument is non-NULL, then it refers to an already- - * loaded shared object, whose library search path will be searched. - * - * The search order is: - * LD_LIBRARY_PATH - * rpath in the referencing file - * ldconfig hints - * /lib:/usr/lib - */ -static char * -find_library(const char *xname, const Obj_Entry *refobj) -{ - char *pathname; - char *name; - - if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ - if (xname[0] != '/' && !trust) { - _rtld_error("Absolute pathname required for shared object \"%s\"", - xname); - return NULL; - } - return xstrdup(xname); - } - - if (libmap_disable || (refobj == NULL) || - (name = lm_find(refobj->path, xname)) == NULL) - name = (char *)xname; - - dbg(" Searching for \"%s\"", name); - - if ((pathname = search_library_path(name, ld_library_path)) != NULL || - (refobj != NULL && - (pathname = search_library_path(name, refobj->rpath)) != NULL) || - (pathname = search_library_path(name, gethints())) != NULL || - (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL) - return pathname; - - if(refobj != NULL && refobj->path != NULL) { - _rtld_error("Shared object \"%s\" not found, required by \"%s\"", - name, basename(refobj->path)); - } else { - _rtld_error("Shared object \"%s\" not found", name); - } - return NULL; -} - -#endif /* 0 */ - -/* - * Given a symbol number in a referencing object, find the corresponding - * definition of the symbol. Returns a pointer to the symbol, or NULL if - * no definition was found. Returns a pointer to the Obj_Entry of the - * defining object via the reference parameter DEFOBJ_OUT. - */ -const Elf_Sym * -find_symdef(unsigned long symnum, const Obj_Entry *refobj, - const Obj_Entry **defobj_out, bool in_plt, SymCache *cache) -{ - const Elf_Sym *ref; - const Elf_Sym *def; - const Obj_Entry *defobj; - const char *name; - unsigned long hash; - - /* - * If we have already found this symbol, get the information from - * the cache. - */ - if (symnum >= refobj->nchains) - return NULL; /* Bad object */ - if (cache != NULL && cache[symnum].sym != NULL) { - *defobj_out = cache[symnum].obj; - return cache[symnum].sym; - } - - ref = refobj->symtab + symnum; - name = refobj->strtab + ref->st_name; - defobj = NULL; - - /* - * We don't have to do a full scale lookup if the symbol is local. - * We know it will bind to the instance in this load module; to - * which we already have a pointer (ie ref). By not doing a lookup, - * we not only improve performance, but it also avoids unresolvable - * symbols when local symbols are not in the hash table. This has - * been seen with the ia64 toolchain. - */ - if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { - if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { - _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, - symnum); - } - hash = elf_hash(name); - def = symlook_default(name, hash, refobj, &defobj, in_plt); - } else { - def = ref; - defobj = refobj; - } - - /* - * If we found no definition and the reference is weak, treat the - * symbol as having the value zero. - */ - if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { - def = &sym_zero; - defobj = obj_main; - } - - if (def != NULL) { - *defobj_out = defobj; - /* Record the information in the cache to avoid subsequent lookups. */ - if (cache != NULL) { - cache[symnum].sym = def; - cache[symnum].obj = defobj; - } - } else { - if (refobj != &obj_rtld) - _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name); - } - return def; -} - -#if 0 - -/* - * Return the search path from the ldconfig hints file, reading it if - * necessary. Returns NULL if there are problems with the hints file, - * or if the search path there is empty. - */ -static const char * -gethints(void) -{ - static char *hints; - - if (hints == NULL) { - int fd; - struct elfhints_hdr hdr; - char *p; - - /* Keep from trying again in case the hints file is bad. */ - hints = ""; - - if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1) - return NULL; - if (read(fd, &hdr, sizeof hdr) != sizeof hdr || - hdr.magic != ELFHINTS_MAGIC || - hdr.version != 1) { - close(fd); - return NULL; - } - p = xmalloc(hdr.dirlistlen + 1); - if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 || - read(fd, p, hdr.dirlistlen + 1) != (ssize_t)hdr.dirlistlen + 1) { - free(p); - close(fd); - return NULL; - } - hints = p; - close(fd); - } - return hints[0] != '\0' ? hints : NULL; -} - -static void -init_dag(Obj_Entry *root) -{ - DoneList donelist; - - donelist_init(&donelist); - init_dag1(root, root, &donelist); -} - -static void -init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp) -{ - const Needed_Entry *needed; - - if (donelist_check(dlp, obj)) - return; - - obj->refcount++; - objlist_push_tail(&obj->dldags, root); - objlist_push_tail(&root->dagmembers, obj); - for (needed = obj->needed; needed != NULL; needed = needed->next) - if (needed->obj != NULL) - init_dag1(root, needed->obj, dlp); -} - -/* - * Initialize the dynamic linker. The argument is the address at which - * the dynamic linker has been mapped into memory. The primary task of - * this function is to relocate the dynamic linker. - */ -static void -init_rtld(caddr_t mapbase) -{ - Obj_Entry objtmp; /* Temporary rtld object */ - - /* - * Conjure up an Obj_Entry structure for the dynamic linker. - * - * The "path" member can't be initialized yet because string constatns - * cannot yet be acessed. Below we will set it correctly. - */ - memset(&objtmp, 0, sizeof(objtmp)); - objtmp.path = NULL; - objtmp.rtld = true; - objtmp.mapbase = mapbase; -#ifdef PIC - objtmp.relocbase = mapbase; -#endif - if (RTLD_IS_DYNAMIC()) { - objtmp.dynamic = rtld_dynamic(&objtmp); - digest_dynamic(&objtmp, 1); - assert(objtmp.needed == NULL); - assert(!objtmp.textrel); - - /* - * Temporarily put the dynamic linker entry into the object list, so - * that symbols can be found. - */ - - relocate_objects(&objtmp, true, &objtmp); - } - - /* Initialize the object list. */ - obj_tail = &obj_list; - - /* Now that non-local variables can be accesses, copy out obj_rtld. */ - memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); - - /* Replace the path with a dynamically allocated copy. */ - obj_rtld.path = xstrdup(PATH_RTLD); - - r_debug.r_brk = r_debug_state; - r_debug.r_state = RT_CONSISTENT; -} - -/* - * Add the init functions from a needed object list (and its recursive - * needed objects) to "list". This is not used directly; it is a helper - * function for initlist_add_objects(). The write lock must be held - * when this function is called. - */ -static void -initlist_add_neededs(Needed_Entry *needed, Objlist *list) -{ - /* Recursively process the successor needed objects. */ - if (needed->next != NULL) - initlist_add_neededs(needed->next, list); - - /* Process the current needed object. */ - if (needed->obj != NULL) - initlist_add_objects(needed->obj, &needed->obj->next, list); -} - -/* - * Scan all of the DAGs rooted in the range of objects from "obj" to - * "tail" and add their init functions to "list". This recurses over - * the DAGs and ensure the proper init ordering such that each object's - * needed libraries are initialized before the object itself. At the - * same time, this function adds the objects to the global finalization - * list "list_fini" in the opposite order. The write lock must be - * held when this function is called. - */ -static void -initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list) -{ - if (obj->init_done) - return; - obj->init_done = true; - - /* Recursively process the successor objects. */ - if (&obj->next != tail) - initlist_add_objects(obj->next, tail, list); - - /* Recursively process the needed objects. */ - if (obj->needed != NULL) - initlist_add_neededs(obj->needed, list); - - /* Add the object to the init list. */ - if (obj->init != (Elf_Addr)NULL) - objlist_push_tail(list, obj); - - /* Add the object to the global fini list in the reverse order. */ - if (obj->fini != (Elf_Addr)NULL) - objlist_push_head(&list_fini, obj); -} - -#ifndef FPTR_TARGET -#define FPTR_TARGET(f) ((Elf_Addr) (f)) -#endif - -static bool -is_exported(const Elf_Sym *def) -{ - Elf_Addr value; - const func_ptr_type *p; - - value = (Elf_Addr)(obj_rtld.relocbase + def->st_value); - for (p = exports; *p != NULL; p++) - if (FPTR_TARGET(*p) == value) - return true; - return false; -} - -/* - * Given a shared object, traverse its list of needed objects, and load - * each of them. Returns 0 on success. Generates an error message and - * returns -1 on failure. - */ -static int -load_needed_objects(Obj_Entry *first) -{ - Obj_Entry *obj; - - for (obj = first; obj != NULL; obj = obj->next) { - Needed_Entry *needed; - - for (needed = obj->needed; needed != NULL; needed = needed->next) { - const char *name = obj->strtab + needed->name; - char *path = find_library(name, obj); - - needed->obj = NULL; - if (path == NULL && !ld_tracing) - return -1; - - if (path) { - needed->obj = load_object(path); - if (needed->obj == NULL && !ld_tracing) - return -1; /* XXX - cleanup */ - } - } - } - - return 0; -} - -static int -load_preload_objects(void) -{ - char *p = ld_preload; - static const char delim[] = " \t:;"; - - if (p == NULL) - return 0; - - p += strspn(p, delim); - while (*p != '\0') { - size_t len = strcspn(p, delim); - char *path; - char savech; - - savech = p[len]; - p[len] = '\0'; - if ((path = find_library(p, NULL)) == NULL) - return -1; - if (load_object(path) == NULL) - return -1; /* XXX - cleanup */ - p[len] = savech; - p += len; - p += strspn(p, delim); - } - return 0; -} - -/* - * Load a shared object into memory, if it is not already loaded. The - * argument must be a string allocated on the heap. This function assumes - * responsibility for freeing it when necessary. - * - * Returns a pointer to the Obj_Entry for the object. Returns NULL - * on failure. - */ -static Obj_Entry * -load_object(char *path) -{ - Obj_Entry *obj; - int fd = -1; - struct stat sb; - - for (obj = obj_list->next; obj != NULL; obj = obj->next) - if (strcmp(obj->path, path) == 0) - break; - - /* - * If we didn't find a match by pathname, open the file and check - * again by device and inode. This avoids false mismatches caused - * by multiple links or ".." in pathnames. - * - * To avoid a race, we open the file and use fstat() rather than - * using stat(). - */ - if (obj == NULL) { - if ((fd = open(path, O_RDONLY)) == -1) { - _rtld_error("Cannot open \"%s\"", path); - return NULL; - } - if (fstat(fd, &sb) == -1) { - _rtld_error("Cannot fstat \"%s\"", path); - close(fd); - return NULL; - } - for (obj = obj_list->next; obj != NULL; obj = obj->next) { - if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) { - close(fd); - break; - } - } - } - - if (obj == NULL) { /* First use of this object, so we must map it in */ - dbg("loading \"%s\"", path); - obj = map_object(fd, path, &sb); - close(fd); - if (obj == NULL) { - free(path); - return NULL; - } - - obj->path = path; - digest_dynamic(obj, 0); - - *obj_tail = obj; - obj_tail = &obj->next; - obj_count++; - linkmap_add(obj); /* for GDB & dlinfo() */ - - dbg(" %p .. %p: %s", obj->mapbase, - obj->mapbase + obj->mapsize - 1, obj->path); - if (obj->textrel) - dbg(" WARNING: %s has impure text", obj->path); - } else - free(path); - - return obj; -} - -static Obj_Entry * -obj_from_addr(const void *addr) -{ - Obj_Entry *obj; - - for (obj = obj_list; obj != NULL; obj = obj->next) { - if (addr < (void *) obj->mapbase) - continue; - if (addr < (void *) (obj->mapbase + obj->mapsize)) - return obj; - } - return NULL; -} - -/* - * Call the finalization functions for each of the objects in "list" - * which are unreferenced. All of the objects are expected to have - * non-NULL fini functions. - */ -static void -objlist_call_fini(Objlist *list) -{ - Objlist_Entry *elm; - char *saved_msg; - - /* - * Preserve the current error message since a fini function might - * call into the dynamic linker and overwrite it. - */ - saved_msg = errmsg_save(); - STAILQ_FOREACH(elm, list, link) { - if (elm->obj->refcount == 0) { - dbg("calling fini function for %s at %p", elm->obj->path, - (void *)elm->obj->fini); - call_initfini_pointer(elm->obj, elm->obj->fini); - } - } - errmsg_restore(saved_msg); -} - -/* - * Call the initialization functions for each of the objects in - * "list". All of the objects are expected to have non-NULL init - * functions. - */ -static void -objlist_call_init(Objlist *list) -{ - Objlist_Entry *elm; - char *saved_msg; - - /* - * Preserve the current error message since an init function might - * call into the dynamic linker and overwrite it. - */ - saved_msg = errmsg_save(); - STAILQ_FOREACH(elm, list, link) { - dbg("calling init function for %s at %p", elm->obj->path, - (void *)elm->obj->init); - call_initfini_pointer(elm->obj, elm->obj->init); - } - errmsg_restore(saved_msg); -} - -static void -objlist_clear(Objlist *list) -{ - Objlist_Entry *elm; - - while (!STAILQ_EMPTY(list)) { - elm = STAILQ_FIRST(list); - STAILQ_REMOVE_HEAD(list, link); - free(elm); - } -} - -static Objlist_Entry * -objlist_find(Objlist *list, const Obj_Entry *obj) -{ - Objlist_Entry *elm; - - STAILQ_FOREACH(elm, list, link) - if (elm->obj == obj) - return elm; - return NULL; -} - -static void -objlist_init(Objlist *list) -{ - STAILQ_INIT(list); -} - -static void -objlist_push_head(Objlist *list, Obj_Entry *obj) -{ - Objlist_Entry *elm; - - elm = NEW(Objlist_Entry); - elm->obj = obj; - STAILQ_INSERT_HEAD(list, elm, link); -} - -static void -objlist_push_tail(Objlist *list, Obj_Entry *obj) -{ - Objlist_Entry *elm; - - elm = NEW(Objlist_Entry); - elm->obj = obj; - STAILQ_INSERT_TAIL(list, elm, link); -} - -static void -objlist_remove(Objlist *list, Obj_Entry *obj) -{ - Objlist_Entry *elm; - - if ((elm = objlist_find(list, obj)) != NULL) { - STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); - free(elm); - } -} - -/* - * Remove all of the unreferenced objects from "list". - */ -static void -objlist_remove_unref(Objlist *list) -{ - Objlist newlist; - Objlist_Entry *elm; - - STAILQ_INIT(&newlist); - while (!STAILQ_EMPTY(list)) { - elm = STAILQ_FIRST(list); - STAILQ_REMOVE_HEAD(list, link); - if (elm->obj->refcount == 0) - free(elm); - else - STAILQ_INSERT_TAIL(&newlist, elm, link); - } - *list = newlist; -} - -#endif /* 0 */ - -/* - * Relocate newly-loaded shared objects. The argument is a pointer to - * the Obj_Entry for the first such object. All objects from the first - * to the end of the list of objects are relocated. Returns 0 on success, - * or -1 on failure. - */ -static int -relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) -{ - Obj_Entry *obj; - - for (obj = first; obj != NULL; obj = obj->next) { - if (obj != rtldobj) - dbg("relocating \"%s\"", obj->path); - if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL || - obj->symtab == NULL || obj->strtab == NULL) { - _rtld_error("%s: Shared object has no run-time symbol table", - obj->path); - return -1; - } - - if (obj->textrel) { - /* There are relocations to the write-protected text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-enable text segment: %s", - obj->path, strerror(errno)); - return -1; - } - } - - /* Process the non-PLT relocations. */ - if (reloc_non_plt(obj, rtldobj)) - return -1; - - if (obj->textrel) { /* Re-protected the text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-protect text segment: %s", - obj->path, strerror(errno)); - return -1; - } - } - - /* Process the PLT relocations. */ - if (reloc_plt(obj) == -1) - return -1; - /* Relocate the jump slots if we are doing immediate binding. */ - if (obj->bind_now || bind_now) - if (reloc_jmpslots(obj) == -1) - return -1; - - - /* - * Set up the magic number and version in the Obj_Entry. These - * were checked in the crt1.o from the original ElfKit, so we - * set them for backward compatibility. - */ - obj->magic = RTLD_MAGIC; - obj->version = RTLD_VERSION; - - /* Set the special PLT or GOT entries. */ - init_pltgot(obj); - } - - return 0; -} - -#if 0 - -/* - * Cleanup procedure. It will be called (by the atexit mechanism) just - * before the process exits. - */ -static void -rtld_exit(void) -{ - Obj_Entry *obj; - - dbg("rtld_exit()"); - /* Clear all the reference counts so the fini functions will be called. */ - for (obj = obj_list; obj != NULL; obj = obj->next) - obj->refcount = 0; - objlist_call_fini(&list_fini); - /* No need to remove the items from the list, since we are exiting. */ - if (!libmap_disable) - lm_fini(); -} - -static void * -path_enumerate(const char *path, path_enum_proc callback, void *arg) -{ -#ifdef COMPAT_32BIT - const char *trans; -#endif - if (path == NULL) - return (NULL); - - path += strspn(path, ":;"); - while (*path != '\0') { - size_t len; - char *res; - - len = strcspn(path, ":;"); -#ifdef COMPAT_32BIT - trans = lm_findn(NULL, path, len); - if (trans) - res = callback(trans, strlen(trans), arg); - else -#endif - res = callback(path, len, arg); - - if (res != NULL) - return (res); - - path += len; - path += strspn(path, ":;"); - } - - return (NULL); -} - -struct try_library_args { - const char *name; - size_t namelen; - char *buffer; - size_t buflen; -}; - -static void * -try_library_path(const char *dir, size_t dirlen, void *param) -{ - struct try_library_args *arg; - - arg = param; - if (*dir == '/' || trust) { - char *pathname; - - if (dirlen + 1 + arg->namelen + 1 > arg->buflen) - return (NULL); - - pathname = arg->buffer; - strncpy(pathname, dir, dirlen); - pathname[dirlen] = '/'; - strcpy(pathname + dirlen + 1, arg->name); - - dbg(" Trying \"%s\"", pathname); - if (access(pathname, F_OK) == 0) { /* We found it */ - pathname = xmalloc(dirlen + 1 + arg->namelen + 1); - strcpy(pathname, arg->buffer); - return (pathname); - } - } - return (NULL); -} - -static char * -search_library_path(const char *name, const char *path) -{ - char *p; - struct try_library_args arg; - - if (path == NULL) - return NULL; - - arg.name = name; - arg.namelen = strlen(name); - arg.buffer = xmalloc(PATH_MAX); - arg.buflen = PATH_MAX; - - p = path_enumerate(path, try_library_path, &arg); - - free(arg.buffer); - - return (p); -} - -int -dlclose(void *handle) -{ - Obj_Entry *root; - int lockstate; - - lockstate = wlock_acquire(rtld_bind_lock); - root = dlcheck(handle); - if (root == NULL) { - wlock_release(rtld_bind_lock, lockstate); - return -1; - } - - /* Unreference the object and its dependencies. */ - root->dl_refcount--; - - unref_dag(root); - - if (root->refcount == 0) { - /* - * The object is no longer referenced, so we must unload it. - * First, call the fini functions with no locks held. - */ - wlock_release(rtld_bind_lock, lockstate); - objlist_call_fini(&list_fini); - lockstate = wlock_acquire(rtld_bind_lock); - objlist_remove_unref(&list_fini); - - /* Finish cleaning up the newly-unreferenced objects. */ - GDB_STATE(RT_DELETE,&root->linkmap); - unload_object(root); - GDB_STATE(RT_CONSISTENT,NULL); - } - wlock_release(rtld_bind_lock, lockstate); - return 0; -} - -const char * -dlerror(void) -{ - char *msg = error_message; - error_message = NULL; - return msg; -} - -/* - * This function is deprecated and has no effect. - */ -void -dllockinit(void *context, - void *(*lock_create)(void *context), - void (*rlock_acquire)(void *lock), - void (*wlock_acquire)(void *lock), - void (*lock_release)(void *lock), - void (*lock_destroy)(void *lock), - void (*context_destroy)(void *context)) -{ - static void *cur_context; - static void (*cur_context_destroy)(void *); - - /* Just destroy the context from the previous call, if necessary. */ - if (cur_context_destroy != NULL) - cur_context_destroy(cur_context); - cur_context = context; - cur_context_destroy = context_destroy; -} - -void * -dlopen(const char *name, int mode) -{ - Obj_Entry **old_obj_tail; - Obj_Entry *obj; - Objlist initlist; - int result, lockstate; - - ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; - if (ld_tracing != NULL) - environ = (char **)*get_program_var_addr("environ"); - - objlist_init(&initlist); - - lockstate = wlock_acquire(rtld_bind_lock); - GDB_STATE(RT_ADD,NULL); - - old_obj_tail = obj_tail; - obj = NULL; - if (name == NULL) { - obj = obj_main; - obj->refcount++; - } else { - char *path = find_library(name, obj_main); - if (path != NULL) - obj = load_object(path); - } - - if (obj) { - obj->dl_refcount++; - if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) - objlist_push_tail(&list_global, obj); - mode &= RTLD_MODEMASK; - if (*old_obj_tail != NULL) { /* We loaded something new. */ - assert(*old_obj_tail == obj); - - result = load_needed_objects(obj); - if (result != -1 && ld_tracing) - goto trace; - - if (result == -1 || - (init_dag(obj), relocate_objects(obj, mode == RTLD_NOW, - &obj_rtld)) == -1) { - obj->dl_refcount--; - unref_dag(obj); - if (obj->refcount == 0) - unload_object(obj); - obj = NULL; - } else { - /* Make list of init functions to call. */ - initlist_add_objects(obj, &obj->next, &initlist); - } - } else { - - /* Bump the reference counts for objects on this DAG. */ - ref_dag(obj); - - if (ld_tracing) - goto trace; - } - } - - GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); - - /* Call the init functions with no locks held. */ - wlock_release(rtld_bind_lock, lockstate); - objlist_call_init(&initlist); - lockstate = wlock_acquire(rtld_bind_lock); - objlist_clear(&initlist); - wlock_release(rtld_bind_lock, lockstate); - return obj; -trace: - trace_loaded_objects(obj); - wlock_release(rtld_bind_lock, lockstate); - exit(0); -} - -void * -dlsym(void *handle, const char *name) -{ - const Obj_Entry *obj; - unsigned long hash; - const Elf_Sym *def; - const Obj_Entry *defobj; - int lockstate; - - hash = elf_hash(name); - def = NULL; - defobj = NULL; - - lockstate = rlock_acquire(rtld_bind_lock); - if (handle == NULL || handle == RTLD_NEXT || - handle == RTLD_DEFAULT || handle == RTLD_SELF) { - void *retaddr; - - retaddr = __builtin_return_address(0); /* __GNUC__ only */ - if ((obj = obj_from_addr(retaddr)) == NULL) { - _rtld_error("Cannot determine caller's shared object"); - rlock_release(rtld_bind_lock, lockstate); - return NULL; - } - if (handle == NULL) { /* Just the caller's shared object. */ - def = symlook_obj(name, hash, obj, true); - defobj = obj; - } else if (handle == RTLD_NEXT || /* Objects after caller's */ - handle == RTLD_SELF) { /* ... caller included */ - if (handle == RTLD_NEXT) - obj = obj->next; - for (; obj != NULL; obj = obj->next) { - if ((def = symlook_obj(name, hash, obj, true)) != NULL) { - defobj = obj; - break; - } - } - } else { - assert(handle == RTLD_DEFAULT); - def = symlook_default(name, hash, obj, &defobj, true); - } - } else { - if ((obj = dlcheck(handle)) == NULL) { - rlock_release(rtld_bind_lock, lockstate); - return NULL; - } - - if (obj->mainprog) { - DoneList donelist; - - /* Search main program and all libraries loaded by it. */ - donelist_init(&donelist); - def = symlook_list(name, hash, &list_main, &defobj, true, - &donelist); - } else { - /* - * XXX - This isn't correct. The search should include the whole - * DAG rooted at the given object. - */ - def = symlook_obj(name, hash, obj, true); - defobj = obj; - } - } - - if (def != NULL) { - rlock_release(rtld_bind_lock, lockstate); - - /* - * The value required by the caller is derived from the value - * of the symbol. For the ia64 architecture, we need to - * construct a function descriptor which the caller can use to - * call the function with the right 'gp' value. For other - * architectures and for non-functions, the value is simply - * the relocated value of the symbol. - */ - if (ELF_ST_TYPE(def->st_info) == STT_FUNC) - return make_function_pointer(def, defobj); - else - return defobj->relocbase + def->st_value; - } - - _rtld_error("Undefined symbol \"%s\"", name); - rlock_release(rtld_bind_lock, lockstate); - return NULL; -} - -int -dladdr(const void *addr, Dl_info *info) -{ - const Obj_Entry *obj; - const Elf_Sym *def; - void *symbol_addr; - unsigned long symoffset; - int lockstate; - - lockstate = rlock_acquire(rtld_bind_lock); - obj = obj_from_addr(addr); - if (obj == NULL) { - _rtld_error("No shared object contains address"); - rlock_release(rtld_bind_lock, lockstate); - return 0; - } - info->dli_fname = obj->path; - info->dli_fbase = obj->mapbase; - info->dli_saddr = (void *)0; - info->dli_sname = NULL; - - /* - * Walk the symbol list looking for the symbol whose address is - * closest to the address sent in. - */ - for (symoffset = 0; symoffset < obj->nchains; symoffset++) { - def = obj->symtab + symoffset; - - /* - * For skip the symbol if st_shndx is either SHN_UNDEF or - * SHN_COMMON. - */ - if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) - continue; - - /* - * If the symbol is greater than the specified address, or if it - * is further away from addr than the current nearest symbol, - * then reject it. - */ - symbol_addr = obj->relocbase + def->st_value; - if (symbol_addr > addr || symbol_addr < info->dli_saddr) - continue; - - /* Update our idea of the nearest symbol. */ - info->dli_sname = obj->strtab + def->st_name; - info->dli_saddr = symbol_addr; - - /* Exact match? */ - if (info->dli_saddr == addr) - break; - } - rlock_release(rtld_bind_lock, lockstate); - return 1; -} - -int -dlinfo(void *handle, int request, void *p) -{ - const Obj_Entry *obj; - int error, lockstate; - - lockstate = rlock_acquire(rtld_bind_lock); - - if (handle == NULL || handle == RTLD_SELF) { - void *retaddr; - - retaddr = __builtin_return_address(0); /* __GNUC__ only */ - if ((obj = obj_from_addr(retaddr)) == NULL) - _rtld_error("Cannot determine caller's shared object"); - } else - obj = dlcheck(handle); - - if (obj == NULL) { - rlock_release(rtld_bind_lock, lockstate); - return (-1); - } - - error = 0; - switch (request) { - case RTLD_DI_LINKMAP: - *((struct link_map const **)p) = &obj->linkmap; - break; - case RTLD_DI_ORIGIN: - error = rtld_dirname(obj->path, p); - break; - - case RTLD_DI_SERINFOSIZE: - case RTLD_DI_SERINFO: - error = do_search_info(obj, request, (struct dl_serinfo *)p); - break; - - default: - _rtld_error("Invalid request %d passed to dlinfo()", request); - error = -1; - } - - rlock_release(rtld_bind_lock, lockstate); - - return (error); -} - -struct fill_search_info_args { - int request; - unsigned int flags; - Dl_serinfo *serinfo; - Dl_serpath *serpath; - char *strspace; -}; - -static void * -fill_search_info(const char *dir, size_t dirlen, void *param) -{ - struct fill_search_info_args *arg; - - arg = param; - - if (arg->request == RTLD_DI_SERINFOSIZE) { - arg->serinfo->dls_cnt ++; - arg->serinfo->dls_size += dirlen + 1; - } else { - struct dl_serpath *s_entry; - - s_entry = arg->serpath; - s_entry->dls_name = arg->strspace; - s_entry->dls_flags = arg->flags; - - strncpy(arg->strspace, dir, dirlen); - arg->strspace[dirlen] = '\0'; - - arg->strspace += dirlen + 1; - arg->serpath++; - } - - return (NULL); -} - -static int -do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info) -{ - struct dl_serinfo _info; - struct fill_search_info_args args; - - args.request = RTLD_DI_SERINFOSIZE; - args.serinfo = &_info; - - _info.dls_size = __offsetof(struct dl_serinfo, dls_serpath); - _info.dls_cnt = 0; - - path_enumerate(ld_library_path, fill_search_info, &args); - path_enumerate(obj->rpath, fill_search_info, &args); - path_enumerate(gethints(), fill_search_info, &args); - path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args); - - - if (request == RTLD_DI_SERINFOSIZE) { - info->dls_size = _info.dls_size; - info->dls_cnt = _info.dls_cnt; - return (0); - } - - if (info->dls_cnt != _info.dls_cnt || info->dls_size != _info.dls_size) { - _rtld_error("Uninitialized Dl_serinfo struct passed to dlinfo()"); - return (-1); - } - - args.request = RTLD_DI_SERINFO; - args.serinfo = info; - args.serpath = &info->dls_serpath[0]; - args.strspace = (char *)&info->dls_serpath[_info.dls_cnt]; - - args.flags = LA_SER_LIBPATH; - if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL) - return (-1); - - args.flags = LA_SER_RUNPATH; - if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL) - return (-1); - - args.flags = LA_SER_CONFIG; - if (path_enumerate(gethints(), fill_search_info, &args) != NULL) - return (-1); - - args.flags = LA_SER_DEFAULT; - if (path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL) - return (-1); - return (0); -} - -static int -rtld_dirname(const char *path, char *bname) -{ - const char *endp; - - /* Empty or NULL string gets treated as "." */ - if (path == NULL || *path == '\0') { - bname[0] = '.'; - bname[1] = '\0'; - return (0); - } - - /* Strip trailing slashes */ - endp = path + strlen(path) - 1; - while (endp > path && *endp == '/') - endp--; - - /* Find the start of the dir */ - while (endp > path && *endp != '/') - endp--; - - /* Either the dir is "/" or there are no slashes */ - if (endp == path) { - bname[0] = *endp == '/' ? '/' : '.'; - bname[1] = '\0'; - return (0); - } else { - do { - endp--; - } while (endp > path && *endp == '/'); - } - - if (endp - path + 2 > PATH_MAX) - { - _rtld_error("Filename is too long: %s", path); - return(-1); - } - - strncpy(bname, path, endp - path + 1); - bname[endp - path + 1] = '\0'; - return (0); -} - -static void -linkmap_add(Obj_Entry *obj) -{ - struct link_map *l = &obj->linkmap; - struct link_map *prev; - - obj->linkmap.l_name = obj->path; - obj->linkmap.l_addr = obj->mapbase; - obj->linkmap.l_ld = obj->dynamic; -#ifdef __mips__ - /* GDB needs load offset on MIPS to use the symbols */ - obj->linkmap.l_offs = obj->relocbase; -#endif - - if (r_debug.r_map == NULL) { - r_debug.r_map = l; - return; - } - - /* - * Scan to the end of the list, but not past the entry for the - * dynamic linker, which we want to keep at the very end. - */ - for (prev = r_debug.r_map; - prev->l_next != NULL && prev->l_next != &obj_rtld.linkmap; - prev = prev->l_next) - ; - - /* Link in the new entry. */ - l->l_prev = prev; - l->l_next = prev->l_next; - if (l->l_next != NULL) - l->l_next->l_prev = l; - prev->l_next = l; -} - -static void -linkmap_delete(Obj_Entry *obj) -{ - struct link_map *l = &obj->linkmap; - - if (l->l_prev == NULL) { - if ((r_debug.r_map = l->l_next) != NULL) - l->l_next->l_prev = NULL; - return; - } - - if ((l->l_prev->l_next = l->l_next) != NULL) - l->l_next->l_prev = l->l_prev; -} - -/* - * Function for the debugger to set a breakpoint on to gain control. - * - * The two parameters allow the debugger to easily find and determine - * what the runtime loader is doing and to whom it is doing it. - * - * When the loadhook trap is hit (r_debug_state, set at program - * initialization), the arguments can be found on the stack: - * - * +8 struct link_map *m - * +4 struct r_debug *rd - * +0 RetAddr - */ -void -r_debug_state(struct r_debug* rd, struct link_map *m) -{ -} - -/* - * Get address of the pointer variable in the main program. - */ -static const void ** -get_program_var_addr(const char *name) -{ - const Obj_Entry *obj; - unsigned long hash; - - hash = elf_hash(name); - for (obj = obj_main; obj != NULL; obj = obj->next) { - const Elf_Sym *def; - - if ((def = symlook_obj(name, hash, obj, false)) != NULL) { - const void **addr; - - addr = (const void **)(obj->relocbase + def->st_value); - return addr; - } - } - return NULL; -} - -/* - * Set a pointer variable in the main program to the given value. This - * is used to set key variables such as "environ" before any of the - * init functions are called. - */ -static void -set_program_var(const char *name, const void *value) -{ - const void **addr; - - if ((addr = get_program_var_addr(name)) != NULL) { - dbg("\"%s\": *%p <-- %p", name, addr, value); - *addr = value; - } -} - -/* - * Given a symbol name in a referencing object, find the corresponding - * definition of the symbol. Returns a pointer to the symbol, or NULL if - * no definition was found. Returns a pointer to the Obj_Entry of the - * defining object via the reference parameter DEFOBJ_OUT. - */ -static const Elf_Sym * -symlook_default(const char *name, unsigned long hash, - const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt) -{ - DoneList donelist; - const Elf_Sym *def; - const Elf_Sym *symp; - const Obj_Entry *obj; - const Obj_Entry *defobj; - const Objlist_Entry *elm; - def = NULL; - defobj = NULL; - donelist_init(&donelist); - - /* Look first in the referencing object if linked symbolically. */ - if (refobj->symbolic && !donelist_check(&donelist, refobj)) { - symp = symlook_obj(name, hash, refobj, in_plt); - if (symp != NULL) { - def = symp; - defobj = refobj; - } - } - - /* Search all objects loaded at program start up. */ - if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { - symp = symlook_list(name, hash, &list_main, &obj, in_plt, &donelist); - if (symp != NULL && - (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { - def = symp; - defobj = obj; - } - } - - /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ - STAILQ_FOREACH(elm, &list_global, link) { - if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt, - &donelist); - if (symp != NULL && - (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { - def = symp; - defobj = obj; - } - } - - /* Search all dlopened DAGs containing the referencing object. */ - STAILQ_FOREACH(elm, &refobj->dldags, link) { - if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt, - &donelist); - if (symp != NULL && - (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { - def = symp; - defobj = obj; - } - } - - /* - * Search the dynamic linker itself, and possibly resolve the - * symbol from there. This is how the application links to - * dynamic linker services such as dlopen. Only the values listed - * in the "exports" array can be resolved from the dynamic linker. - */ - if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { - symp = symlook_obj(name, hash, &obj_rtld, in_plt); - if (symp != NULL && is_exported(symp)) { - def = symp; - defobj = &obj_rtld; - } - } - - if (def != NULL) - *defobj_out = defobj; - return def; -} - -static const Elf_Sym * -symlook_list(const char *name, unsigned long hash, Objlist *objlist, - const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp) -{ - const Elf_Sym *symp; - const Elf_Sym *def; - const Obj_Entry *defobj; - const Objlist_Entry *elm; - - def = NULL; - defobj = NULL; - STAILQ_FOREACH(elm, objlist, link) { - if (donelist_check(dlp, elm->obj)) - continue; - if ((symp = symlook_obj(name, hash, elm->obj, in_plt)) != NULL) { - if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { - def = symp; - defobj = elm->obj; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - } - } - } - if (def != NULL) - *defobj_out = defobj; - return def; -} - -#endif /* 0 */ - -/* - * Search the symbol table of a single shared object for a symbol of - * the given name. Returns a pointer to the symbol, or NULL if no - * definition was found. - * - * The symbol's hash value is passed in for efficiency reasons; that - * eliminates many recomputations of the hash value. - */ -const Elf_Sym * -symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj, - bool in_plt) -{ - if (obj->buckets != NULL) { - unsigned long symnum = obj->buckets[hash % obj->nbuckets]; - - while (symnum != STN_UNDEF) { - const Elf_Sym *symp; - const char *strp; - - if (symnum >= obj->nchains) - return NULL; /* Bad object */ - symp = obj->symtab + symnum; - strp = obj->strtab + symp->st_name; - - if (name[0] == strp[0] && strcmp(name, strp) == 0) - return symp->st_shndx != SHN_UNDEF || - (!in_plt && symp->st_value != 0 && - ELF_ST_TYPE(symp->st_info) == STT_FUNC) ? symp : NULL; - - symnum = obj->chains[symnum]; - } - } - return NULL; -} - -#if 0 - -static void -trace_loaded_objects(Obj_Entry *obj) -{ - char *fmt1, *fmt2, *fmt, *main_local, *list_containers; - int c; - - if ((main_local = getenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) - main_local = ""; - - if ((fmt1 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT1")) == NULL) - fmt1 = "\t%o => %p (%x)\n"; - - if ((fmt2 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT2")) == NULL) - fmt2 = "\t%o (%x)\n"; - - list_containers = getenv(LD_ "TRACE_LOADED_OBJECTS_ALL"); - - for (; obj; obj = obj->next) { - Needed_Entry *needed; - char *name, *path; - bool is_lib; - - if (list_containers && obj->needed != NULL) - printf("%s:\n", obj->path); - for (needed = obj->needed; needed; needed = needed->next) { - if (needed->obj != NULL) { - if (needed->obj->traced && !list_containers) - continue; - needed->obj->traced = true; - path = needed->obj->path; - } else - path = "not found"; - - name = (char *)obj->strtab + needed->name; - is_lib = strncmp(name, "lib", 3) == 0; /* XXX - bogus */ - - fmt = is_lib ? fmt1 : fmt2; - while ((c = *fmt++) != '\0') { - switch (c) { - default: - putchar(c); - continue; - case '\\': - switch (c = *fmt) { - case '\0': - continue; - case 'n': - putchar('\n'); - break; - case 't': - putchar('\t'); - break; - } - break; - case '%': - switch (c = *fmt) { - case '\0': - continue; - case '%': - default: - putchar(c); - break; - case 'A': - printf("%s", main_local); - break; - case 'a': - printf("%s", obj_main->path); - break; - case 'o': - printf("%s", name); - break; -#if 0 - case 'm': - printf("%d", sodp->sod_major); - break; - case 'n': - printf("%d", sodp->sod_minor); - break; -#endif - case 'p': - printf("%s", path); - break; - case 'x': - printf("%p", needed->obj ? needed->obj->mapbase : 0); - break; - } - break; - } - ++fmt; - } - } - } -} - -/* - * Unload a dlopened object and its dependencies from memory and from - * our data structures. It is assumed that the DAG rooted in the - * object has already been unreferenced, and that the object has a - * reference count of 0. - */ -static void -unload_object(Obj_Entry *root) -{ - Obj_Entry *obj; - Obj_Entry **linkp; - - assert(root->refcount == 0); - - /* - * Pass over the DAG removing unreferenced objects from - * appropriate lists. - */ - unlink_object(root); - - /* Unmap all objects that are no longer referenced. */ - linkp = &obj_list->next; - while ((obj = *linkp) != NULL) { - if (obj->refcount == 0) { - dbg("unloading \"%s\"", obj->path); - munmap(obj->mapbase, obj->mapsize); - linkmap_delete(obj); - *linkp = obj->next; - obj_count--; - obj_free(obj); - } else - linkp = &obj->next; - } - obj_tail = linkp; -} - -static void -unlink_object(Obj_Entry *root) -{ - Objlist_Entry *elm; - - if (root->refcount == 0) { - /* Remove the object from the RTLD_GLOBAL list. */ - objlist_remove(&list_global, root); - - /* Remove the object from all objects' DAG lists. */ - STAILQ_FOREACH(elm, &root->dagmembers , link) { - objlist_remove(&elm->obj->dldags, root); - if (elm->obj != root) - unlink_object(elm->obj); - } - } -} - -static void -ref_dag(Obj_Entry *root) -{ - Objlist_Entry *elm; - - STAILQ_FOREACH(elm, &root->dagmembers , link) - elm->obj->refcount++; -} - -static void -unref_dag(Obj_Entry *root) -{ - Objlist_Entry *elm; - - STAILQ_FOREACH(elm, &root->dagmembers , link) - elm->obj->refcount--; -} - -/* - * Common code for MD __tls_get_addr(). - */ -void * -tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset) -{ - Elf_Addr* dtv = *dtvp; - - /* Check dtv generation in case new modules have arrived */ - if (dtv[0] != tls_dtv_generation) { - Elf_Addr* newdtv; - int to_copy; - - newdtv = calloc(1, (tls_max_index + 2) * sizeof(Elf_Addr)); - to_copy = dtv[1]; - if (to_copy > tls_max_index) - to_copy = tls_max_index; - memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr)); - newdtv[0] = tls_dtv_generation; - newdtv[1] = tls_max_index; - free(dtv); - *dtvp = newdtv; - } - - /* Dynamically allocate module TLS if necessary */ - if (!dtv[index + 1]) - dtv[index + 1] = (Elf_Addr)allocate_module_tls(index); - - return (void*) (dtv[index + 1] + offset); -} - -/* XXX not sure what variants to use for arm. */ - -#if defined(__ia64__) || defined(__alpha__) || defined(__powerpc__) - -/* - * Allocate Static TLS using the Variant I method. - */ -void * -allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) -{ - Obj_Entry *obj; - size_t size; - char *tls; - Elf_Addr *dtv, *olddtv; - Elf_Addr addr; - int i; - - size = tls_static_space; - - tls = malloc(size); - dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr)); - - *(Elf_Addr**) tls = dtv; - - dtv[0] = tls_dtv_generation; - dtv[1] = tls_max_index; - - if (oldtls) { - /* - * Copy the static TLS block over whole. - */ - memcpy(tls + tcbsize, oldtls + tcbsize, tls_static_space - tcbsize); - - /* - * If any dynamic TLS blocks have been created tls_get_addr(), - * move them over. - */ - olddtv = *(Elf_Addr**) oldtls; - for (i = 0; i < olddtv[1]; i++) { - if (olddtv[i+2] < (Elf_Addr)oldtls || - olddtv[i+2] > (Elf_Addr)oldtls + tls_static_space) { - dtv[i+2] = olddtv[i+2]; - olddtv[i+2] = 0; - } - } - - /* - * We assume that all tls blocks are allocated with the same - * size and alignment. - */ - free_tls(oldtls, tcbsize, tcbalign); - } else { - for (obj = objs; obj; obj = obj->next) { - if (obj->tlsoffset) { - addr = (Elf_Addr)tls + obj->tlsoffset; - memset((void*) (addr + obj->tlsinitsize), - 0, obj->tlssize - obj->tlsinitsize); - if (obj->tlsinit) - memcpy((void*) addr, obj->tlsinit, - obj->tlsinitsize); - dtv[obj->tlsindex + 1] = addr; - } else if (obj->tlsindex) { - dtv[obj->tlsindex + 1] = 0; - } - } - } - - return tls; -} - -void -free_tls(void *tls, size_t tcbsize, size_t tcbalign) -{ - size_t size; - Elf_Addr* dtv; - int dtvsize, i; - Elf_Addr tlsstart, tlsend; - - /* - * Figure out the size of the initial TLS block so that we can - * find stuff which __tls_get_addr() allocated dynamically. - */ - size = tls_static_space; - - dtv = ((Elf_Addr**)tls)[0]; - dtvsize = dtv[1]; - tlsstart = (Elf_Addr) tls; - tlsend = tlsstart + size; - for (i = 0; i < dtvsize; i++) { - if (dtv[i+2] < tlsstart || dtv[i+2] > tlsend) { - free((void*) dtv[i+2]); - } - } - - free((void*) tlsstart); -} - -#endif - -#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ - defined(__arm__) - -/* - * Allocate Static TLS using the Variant II method. - */ -void * -allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) -{ - Obj_Entry *obj; - size_t size; - char *tls; - Elf_Addr *dtv, *olddtv; - Elf_Addr segbase, oldsegbase, addr; - int i; - - size = round(tls_static_space, tcbalign); - - assert(tcbsize >= 2*sizeof(Elf_Addr)); - tls = malloc(size + tcbsize); - dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr)); - - segbase = (Elf_Addr)(tls + size); - ((Elf_Addr*)segbase)[0] = segbase; - ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; - - dtv[0] = tls_dtv_generation; - dtv[1] = tls_max_index; - - if (oldtls) { - /* - * Copy the static TLS block over whole. - */ - oldsegbase = (Elf_Addr) oldtls; - memcpy((void *)(segbase - tls_static_space), - (const void *)(oldsegbase - tls_static_space), - tls_static_space); - - /* - * If any dynamic TLS blocks have been created tls_get_addr(), - * move them over. - */ - olddtv = ((Elf_Addr**)oldsegbase)[1]; - for (i = 0; i < olddtv[1]; i++) { - if (olddtv[i+2] < oldsegbase - size || olddtv[i+2] > oldsegbase) { - dtv[i+2] = olddtv[i+2]; - olddtv[i+2] = 0; - } - } - - /* - * We assume that this block was the one we created with - * allocate_initial_tls(). - */ - free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); - } else { - for (obj = objs; obj; obj = obj->next) { - if (obj->tlsoffset) { - addr = segbase - obj->tlsoffset; - memset((void*) (addr + obj->tlsinitsize), - 0, obj->tlssize - obj->tlsinitsize); - if (obj->tlsinit) - memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); - dtv[obj->tlsindex + 1] = addr; - } else if (obj->tlsindex) { - dtv[obj->tlsindex + 1] = 0; - } - } - } - - return (void*) segbase; -} - -void -free_tls(void *tls, size_t tcbsize, size_t tcbalign) -{ - size_t size; - Elf_Addr* dtv; - int dtvsize, i; - Elf_Addr tlsstart, tlsend; - - /* - * Figure out the size of the initial TLS block so that we can - * find stuff which ___tls_get_addr() allocated dynamically. - */ - size = round(tls_static_space, tcbalign); - - dtv = ((Elf_Addr**)tls)[1]; - dtvsize = dtv[1]; - tlsend = (Elf_Addr) tls; - tlsstart = tlsend - size; - for (i = 0; i < dtvsize; i++) { - if (dtv[i+2] < tlsstart || dtv[i+2] > tlsend) { - free((void*) dtv[i+2]); - } - } - - free((void*) tlsstart); -} - -#endif - -/* - * Allocate TLS block for module with given index. - */ -void * -allocate_module_tls(int index) -{ - Obj_Entry* obj; - char* p; - - for (obj = obj_list; obj; obj = obj->next) { - if (obj->tlsindex == index) - break; - } - if (!obj) { - _rtld_error("Can't find module with TLS index %d", index); - die(); - } - - p = malloc(obj->tlssize); - memcpy(p, obj->tlsinit, obj->tlsinitsize); - memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); - - return p; -} - -bool -allocate_tls_offset(Obj_Entry *obj) -{ - size_t off; - - if (obj->tls_done) - return true; - - if (obj->tlssize == 0) { - obj->tls_done = true; - return true; - } - - if (obj->tlsindex == 1) - off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign); - else - off = calculate_tls_offset(tls_last_offset, tls_last_size, - obj->tlssize, obj->tlsalign); - - /* - * If we have already fixed the size of the static TLS block, we - * must stay within that size. When allocating the static TLS, we - * leave a small amount of space spare to be used for dynamically - * loading modules which use static TLS. - */ - if (tls_static_space) { - if (calculate_tls_end(off, obj->tlssize) > tls_static_space) - return false; - } - - tls_last_offset = obj->tlsoffset = off; - tls_last_size = obj->tlssize; - obj->tls_done = true; - - return true; -} - -void * -_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) -{ - return allocate_tls(obj_list, oldtls, tcbsize, tcbalign); -} - -void -_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) -{ - free_tls(tcb, tcbsize, tcbalign); -} - -#endif /* 0 */ diff --git a/dll/ntdll/ldr/ldrapi.c b/dll/ntdll/ldr/ldrapi.c index 7ba87929ce4..a2f11f8a701 100644 --- a/dll/ntdll/ldr/ldrapi.c +++ b/dll/ntdll/ldr/ldrapi.c @@ -15,12 +15,22 @@ /* GLOBALS *******************************************************************/ +LIST_ENTRY LdrpUnloadHead; LONG LdrpLoaderLockAcquisitonCount; -BOOLEAN LdrpShowRecursiveLoads; +BOOLEAN LdrpShowRecursiveLoads, LdrpBreakOnRecursiveDllLoads; UNICODE_STRING LdrApiDefaultExtension = RTL_CONSTANT_STRING(L".DLL"); /* FUNCTIONS *****************************************************************/ +ULONG_PTR +FORCEINLINE +LdrpMakeCookie(VOID) +{ + /* Generate a cookie */ + return (((ULONG_PTR)NtCurrentTeb()->RealClientId.UniqueThread & 0xFFF) << 16) | + _InterlockedIncrement(&LdrpLoaderLockAcquisitonCount); +} + /* * @implemented */ @@ -34,19 +44,17 @@ LdrUnlockLoaderLock(IN ULONG Flags, DPRINT("LdrUnlockLoaderLock(%x %x)\n", Flags, Cookie); /* Check for valid flags */ - if (Flags & ~1) + if (Flags & ~LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) { /* Flags are invalid, check how to fail */ - if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) + if (Flags & LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) { /* The caller wants us to raise status */ RtlRaiseStatus(STATUS_INVALID_PARAMETER_1); } - else - { - /* A normal failure */ - return STATUS_INVALID_PARAMETER_1; - } + + /* A normal failure */ + return STATUS_INVALID_PARAMETER_1; } /* If we don't have a cookie, just return */ @@ -59,20 +67,18 @@ LdrUnlockLoaderLock(IN ULONG Flags, DPRINT1("LdrUnlockLoaderLock() called with an invalid cookie!\n"); /* Invalid cookie, check how to fail */ - if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) + if (Flags & LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) { /* The caller wants us to raise status */ RtlRaiseStatus(STATUS_INVALID_PARAMETER_2); } - else - { - /* A normal failure */ - return STATUS_INVALID_PARAMETER_2; - } + + /* A normal failure */ + return STATUS_INVALID_PARAMETER_2; } /* Ready to release the lock */ - if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) + if (Flags & LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) { /* Do a direct leave */ RtlLeaveCriticalSection(&LdrpLoaderLock); @@ -103,17 +109,16 @@ LdrUnlockLoaderLock(IN ULONG Flags, NTSTATUS NTAPI LdrLockLoaderLock(IN ULONG Flags, - OUT PULONG Result OPTIONAL, - OUT PULONG Cookie OPTIONAL) + OUT PULONG Disposition OPTIONAL, + OUT PULONG_PTR Cookie OPTIONAL) { - LONG OldCount; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN InInit = LdrpInLdrInit; - DPRINT("LdrLockLoaderLock(%x %p %p)\n", Flags, Result, Cookie); + DPRINT("LdrLockLoaderLock(%x %p %p)\n", Flags, Disposition, Cookie); /* Zero out the outputs */ - if (Result) *Result = 0; + if (Disposition) *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID; if (Cookie) *Cookie = 0; /* Validate the flags */ @@ -145,8 +150,11 @@ LdrLockLoaderLock(IN ULONG Flags, return STATUS_INVALID_PARAMETER_3; } + /* Do or Do Not. There is no Try */ + ASSERT((Disposition != NULL) || !(Flags & LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY)); + /* If the flag is set, make sure we have a valid pointer to use */ - if ((Flags & LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY) && !(Result)) + if ((Flags & LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY) && !(Disposition)) { /* No pointer to return the data to */ if (Flags & LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS) @@ -172,13 +180,13 @@ LdrLockLoaderLock(IN ULONG Flags, if (!RtlTryEnterCriticalSection(&LdrpLoaderLock)) { /* It's locked */ - *Result = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED; - goto Quickie; + *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED; } else { /* It worked */ - *Result = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + *Cookie = LdrpMakeCookie(); } } else @@ -187,14 +195,9 @@ LdrLockLoaderLock(IN ULONG Flags, RtlEnterCriticalSection(&LdrpLoaderLock); /* See if result was requested */ - if (Result) *Result = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + if (Disposition) *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + *Cookie = LdrpMakeCookie(); } - - /* Increase the acquisition count */ - OldCount = _InterlockedIncrement(&LdrpLoaderLockAcquisitonCount); - - /* Generate a cookie */ - *Cookie = (((ULONG)NtCurrentTeb()->RealClientId.UniqueThread & 0xFFF) << 16) | OldCount; } else { @@ -208,13 +211,13 @@ LdrLockLoaderLock(IN ULONG Flags, if (!RtlTryEnterCriticalSection(&LdrpLoaderLock)) { /* It's locked */ - *Result = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED; - _SEH2_YIELD(return STATUS_SUCCESS); + *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED; } else { /* It worked */ - *Result = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + *Cookie = LdrpMakeCookie(); } } else @@ -223,14 +226,9 @@ LdrLockLoaderLock(IN ULONG Flags, RtlEnterCriticalSection(&LdrpLoaderLock); /* See if result was requested */ - if (Result) *Result = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + if (Disposition) *Disposition = LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED; + *Cookie = LdrpMakeCookie(); } - - /* Increase the acquisition count */ - OldCount = _InterlockedIncrement(&LdrpLoaderLockAcquisitonCount); - - /* Generate a cookie */ - *Cookie = (((ULONG)NtCurrentTeb()->RealClientId.UniqueThread & 0xFFF) << 16) | OldCount; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -240,7 +238,7 @@ LdrLockLoaderLock(IN ULONG Flags, _SEH2_END; } -Quickie: + /* Return status */ return Status; } @@ -263,7 +261,7 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL, PTEB Teb = NtCurrentTeb(); /* Initialize the strings */ - RtlInitUnicodeString(&DllString2, NULL); + RtlInitEmptyUnicodeString(&DllString2, NULL, 0); DllString1.Buffer = StringBuffer; DllString1.Length = 0; DllString1.MaximumLength = sizeof(StringBuffer); @@ -288,11 +286,7 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL, else if (Status != STATUS_SXS_KEY_NOT_FOUND) { /* Unrecoverable SxS failure; did we get a string? */ - if (DllString2.Buffer) - { - /* Free the string */ - RtlFreeUnicodeString(&DllString2); - } + if (DllString2.Buffer) RtlFreeUnicodeString(&DllString2); return Status; } @@ -300,10 +294,11 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL, LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie); /* Check if there's a TLD DLL being loaded */ - if ((OldTldDll = LdrpTopLevelDllBeingLoaded)) + OldTldDll = LdrpTopLevelDllBeingLoaded; + if (OldTldDll) { /* This is a recursive load, do something about it? */ - if (ShowSnaps || LdrpShowRecursiveLoads) + if ((ShowSnaps) || (LdrpShowRecursiveLoads) || (LdrpBreakOnRecursiveDllLoads)) { /* Print out debug messages */ DPRINT1("[%lx, %lx] LDR: Recursive DLL Load\n", @@ -345,6 +340,23 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL, DllName, BaseAddress, TRUE); + if (NT_SUCCESS(Status)) + { + Status = STATUS_SUCCESS; + } + else if ((Status != STATUS_NO_SUCH_FILE) && + (Status != STATUS_DLL_NOT_FOUND) && + (Status != STATUS_OBJECT_NAME_NOT_FOUND) && + (Status != STATUS_DLL_INIT_FAILED)) + { + // 85 == DPFLTR_LDR_ID; + DbgPrintEx(85, + DPFLTR_WARNING_LEVEL, + "LDR: %s - failing because LdrpLoadDll(%wZ) returned status %x\n", + __FUNCTION__, + DllName, + Status); + } /* Restore the old TLD DLL */ LdrpTopLevelDllBeingLoaded = OldTldDll; @@ -378,6 +390,29 @@ LdrFindEntryForAddress(PVOID Address, /* Nothing to do */ if (!Ldr) return STATUS_NO_MORE_ENTRIES; + /* Get the current entry */ + LdrEntry = Ldr->EntryInProgress; + if (LdrEntry) + { + /* Get the NT Headers */ + NtHeader = RtlImageNtHeader(LdrEntry->DllBase); + if (NtHeader) + { + /* Get the Image Base */ + DllBase = (ULONG_PTR)LdrEntry->DllBase; + DllEnd = DllBase + NtHeader->OptionalHeader.SizeOfImage; + + /* Check if they match */ + if (((ULONG_PTR)Address >= DllBase) && + ((ULONG_PTR)Address < DllEnd)) + { + /* Return it */ + *Module = LdrEntry; + return STATUS_SUCCESS; + } + } + } + /* Loop the module list */ ListHead = &Ldr->InMemoryOrderModuleList; NextEntry = ListHead->Flink; @@ -385,7 +420,8 @@ LdrFindEntryForAddress(PVOID Address, { /* Get the entry and NT Headers */ LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList); - if ((NtHeader = RtlImageNtHeader(LdrEntry->DllBase))) + NtHeader = RtlImageNtHeader(LdrEntry->DllBase); + if (NtHeader) { /* Get the Image Base */ DllBase = (ULONG_PTR)LdrEntry->DllBase; @@ -406,6 +442,8 @@ LdrFindEntryForAddress(PVOID Address, } /* Nothing found */ + // 85 == DPFLTR_LDR_ID; + DbgPrintEx(85, DPFLTR_WARNING_LEVEL, "LDR: %s() exiting 0x%08lx\n", __FUNCTION__, STATUS_NO_MORE_ENTRIES); return STATUS_NO_MORE_ENTRIES; } @@ -420,31 +458,36 @@ LdrGetDllHandleEx(IN ULONG Flags, IN PUNICODE_STRING DllName, OUT PVOID *DllHandle OPTIONAL) { - NTSTATUS Status = STATUS_DLL_NOT_FOUND; + NTSTATUS Status; PLDR_DATA_TABLE_ENTRY LdrEntry; - UNICODE_STRING RedirectName, DllString1; - UNICODE_STRING RawDllName; - PUNICODE_STRING pRedirectName = &RedirectName; - PUNICODE_STRING CompareName; + UNICODE_STRING RedirectName, DllString1, RawDllName; + PUNICODE_STRING pRedirectName, CompareName; PWCHAR p1, p2, p3; - BOOLEAN Locked = FALSE; - BOOLEAN RedirectedDll = FALSE; - ULONG Cookie; - ULONG LoadFlag; + BOOLEAN Locked, RedirectedDll; + ULONG_PTR Cookie; + ULONG LoadFlag, Length; /* Initialize the strings */ - RtlInitUnicodeString(&DllString1, NULL); - RtlInitUnicodeString(&RawDllName, NULL); + RtlInitEmptyUnicodeString(&DllString1, NULL, 0); + RtlInitEmptyUnicodeString(&RawDllName, NULL, 0); RedirectName = *DllName; + pRedirectName = &RedirectName; + + /* Initialize state */ + RedirectedDll = Locked = FALSE; + LdrEntry = NULL; + Cookie = 0; /* Clear the handle */ if (DllHandle) *DllHandle = NULL; - /* Check for a valid flag */ - if ((Flags & ~3) || (!DllHandle && !(Flags & 2))) + /* Check for a valid flag combination */ + if ((Flags & ~(LDR_GET_DLL_HANDLE_EX_PIN | LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT)) || + (!DllHandle && !(Flags & LDR_GET_DLL_HANDLE_EX_PIN))) { DPRINT1("Flags are invalid or no DllHandle given\n"); - return STATUS_INVALID_PARAMETER; + Status = STATUS_INVALID_PARAMETER; + goto Quickie; } /* If not initializing */ @@ -452,6 +495,9 @@ LdrGetDllHandleEx(IN ULONG Flags, { /* Acquire the lock */ Status = LdrLockLoaderLock(0, NULL, &Cookie); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Remember we own it */ Locked = TRUE; } @@ -477,6 +523,13 @@ LdrGetDllHandleEx(IN ULONG Flags, /* Unrecoverable SxS failure; */ goto Quickie; } + else + { + ASSERT(pRedirectName == &RedirectName); + } + + /* Set default failure code */ + Status = STATUS_DLL_NOT_FOUND; /* Use the cache if we can */ if (LdrpGetModuleHandleCache) @@ -485,28 +538,24 @@ LdrGetDllHandleEx(IN ULONG Flags, if (RedirectedDll) { /* Check the flag */ - if (LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED) - { - /* Use the right name */ - CompareName = &LdrpGetModuleHandleCache->FullDllName; - } - else + if (!(LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED)) { goto DontCompare; } + + /* Use the right name */ + CompareName = &LdrpGetModuleHandleCache->FullDllName; } else { /* Check the flag */ - if (!(LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED)) - { - /* Use the right name */ - CompareName = &LdrpGetModuleHandleCache->BaseDllName; - } - else + if (LdrpGetModuleHandleCache->Flags & LDRP_REDIRECTED) { goto DontCompare; } + + /* Use the right name */ + CompareName = &LdrpGetModuleHandleCache->BaseDllName; } /* Check if the name matches */ @@ -519,17 +568,15 @@ LdrGetDllHandleEx(IN ULONG Flags, /* Return success */ Status = STATUS_SUCCESS; - - goto FoundEntry; + goto Quickie; } } DontCompare: /* Find the name without the extension */ p1 = pRedirectName->Buffer; - p3 = &p1[pRedirectName->Length / sizeof(WCHAR)]; -StartLoop: p2 = NULL; + p3 = &p1[pRedirectName->Length / sizeof(WCHAR)]; while (p1 != p3) { if (*p1++ == L'.') @@ -538,48 +585,47 @@ StartLoop: } else if (*p1 == L'\\') { - goto StartLoop; + p2 = NULL; } } /* Check if no extension was found or if we got a slash */ - if (!p2 || *p2 == L'\\' || *p2 == L'/') + if (!(p2) || (*p2 == L'\\') || (*p2 == L'/')) { /* Check that we have space to add one */ - if (pRedirectName->Length + LdrApiDefaultExtension.Length >= MAXLONG) + Length = pRedirectName->Length + + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL); + if (Length >= UNICODE_STRING_MAX_BYTES) { /* No space to add the extension */ - return STATUS_NAME_TOO_LONG; + Status = STATUS_NAME_TOO_LONG; + goto Quickie; } /* Setup the string */ - RawDllName.MaximumLength = pRedirectName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL); - RawDllName.Length = RawDllName.MaximumLength - sizeof(UNICODE_NULL); + RawDllName.MaximumLength = Length; + ASSERT(Length >= sizeof(UNICODE_NULL)); RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RawDllName.MaximumLength); + if (!RawDllName.Buffer) + { + Status = STATUS_NO_MEMORY; + goto Quickie; + } - /* Copy the buffer */ - RtlMoveMemory(RawDllName.Buffer, - pRedirectName->Buffer, - pRedirectName->Length); - - /* Add extension */ - RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName.Buffer + pRedirectName->Length), - LdrApiDefaultExtension.Buffer, - LdrApiDefaultExtension.Length); - - /* Null terminate */ - RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL; + /* Copy the string and add extension */ + RtlCopyUnicodeString(&RawDllName, pRedirectName); + RtlAppendUnicodeStringToString(&RawDllName, &LdrApiDefaultExtension); } else { /* Check if there's something in the name */ - if (pRedirectName->Length) + Length = pRedirectName->Length; + if (Length) { /* Check and remove trailing period */ - if (pRedirectName->Buffer[(pRedirectName->Length - 2) / - sizeof(WCHAR)] == '.') + if (pRedirectName->Buffer[Length / sizeof(WCHAR) - sizeof(ANSI_NULL)] == '.') { /* Decrease the size */ pRedirectName->Length -= sizeof(WCHAR); @@ -588,24 +634,23 @@ StartLoop: /* Setup the string */ RawDllName.MaximumLength = pRedirectName->Length + sizeof(WCHAR); - RawDllName.Length = pRedirectName->Length; RawDllName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, RawDllName.MaximumLength); + if (!RawDllName.Buffer) + { + Status = STATUS_NO_MEMORY; + goto Quickie; + } - /* Copy the buffer */ - RtlMoveMemory(RawDllName.Buffer, - pRedirectName->Buffer, - pRedirectName->Length); - - /* Null terminate */ - RawDllName.Buffer[RawDllName.Length / sizeof(WCHAR)] = UNICODE_NULL; + /* Copy the string */ + RtlCopyUnicodeString(&RawDllName, pRedirectName); } /* Display debug string */ if (ShowSnaps) { - DPRINT1("LDR: LdrGetDllHandle, searching for %wZ from %ws\n", + DPRINT1("LDR: LdrGetDllHandleEx, searching for %wZ from %ws\n", &RawDllName, DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L""); } @@ -628,46 +673,41 @@ StartLoop: /* Make sure to NULL this */ LdrEntry = NULL; } -FoundEntry: - DPRINT("Got LdrEntry->BaseDllName %wZ\n", LdrEntry ? &LdrEntry->BaseDllName : NULL); +Quickie: + /* The success path must have a valid loader entry */ + ASSERT((LdrEntry != NULL) == NT_SUCCESS(Status)); - /* Check if we got an entry */ - if (LdrEntry) + /* Check if we got an entry and success */ + DPRINT("Got LdrEntry->BaseDllName %wZ\n", LdrEntry ? &LdrEntry->BaseDllName : NULL); + if ((LdrEntry) && (NT_SUCCESS(Status))) { - /* Check for success */ - if (NT_SUCCESS(Status)) + /* Check if the DLL is locked */ + if ((LdrEntry->LoadCount != 0xFFFF) && + !(Flags & LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT)) { - /* Check if the DLL is locked */ - if (LdrEntry->LoadCount != -1) + /* Check what to do with the load count */ + if (Flags & LDR_GET_DLL_HANDLE_EX_PIN) { - /* Check what flag we got */ - if (!(Flags & 1)) - { - /* Check what to do with the load count */ - if (Flags & 2) - { - /* Pin it */ - LdrEntry->LoadCount = -1; - LoadFlag = LDRP_UPDATE_PIN; - } - else - { - /* Increase the load count */ - LdrEntry->LoadCount++; - LoadFlag = LDRP_UPDATE_REFCOUNT; - } - - /* Update the load count now */ - LdrpUpdateLoadCount2(LdrEntry, LoadFlag); - LdrpClearLoadInProgress(); - } + /* Pin it */ + LdrEntry->LoadCount = 0xFFFF; + LoadFlag = LDRP_UPDATE_PIN; + } + else + { + /* Increase the load count */ + LdrEntry->LoadCount++; + LoadFlag = LDRP_UPDATE_REFCOUNT; } - /* Check if the caller is requesting the handle */ - if (DllHandle) *DllHandle = LdrEntry->DllBase; + /* Update the load count now */ + LdrpUpdateLoadCount2(LdrEntry, LoadFlag); + LdrpClearLoadInProgress(); } + + /* Check if the caller is requesting the handle */ + if (DllHandle) *DllHandle = LdrEntry->DllBase; } -Quickie: + /* Free string if needed */ if (DllString1.Buffer) RtlFreeUnicodeString(&DllString1); @@ -680,7 +720,11 @@ Quickie: } /* Release lock */ - if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + if (Locked) + { + LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, + Cookie); + } /* Return */ return Status; @@ -697,7 +741,7 @@ LdrGetDllHandle(IN PWSTR DllPath OPTIONAL, OUT PVOID *DllHandle) { /* Call the newer API */ - return LdrGetDllHandleEx(TRUE, + return LdrGetDllHandleEx(LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT, DllPath, DllCharacteristics, DllName, @@ -734,15 +778,17 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle, IO_STATUS_BLOCK IoStatusBlock; PIMAGE_NT_HEADERS NtHeader; HANDLE SectionHandle; - SIZE_T ViewSize = 0; - PVOID ViewBase = NULL; - BOOLEAN Result; + SIZE_T ViewSize; + PVOID ViewBase; + BOOLEAN Result, NoActualCheck; NTSTATUS Status; PVOID ImportName; ULONG Size; - DPRINT("LdrVerifyImageMatchesChecksum() called\n"); + /* If the handle has the magic KnownDll flag, skip actual checksums */ + NoActualCheck = ((ULONG_PTR)FileHandle & 1); + /* Create the section */ Status = NtCreateSection(&SectionHandle, SECTION_MAP_EXECUTE, @@ -758,6 +804,8 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle, } /* Map the section */ + ViewSize = 0; + ViewBase = NULL; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &ViewBase, @@ -792,13 +840,22 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle, /* Protect with SEH */ _SEH2_TRY { - /* Verify the checksum */ - Result = LdrVerifyMappedImageMatchesChecksum(ViewBase, - ViewSize, - FileStandardInfo.EndOfFile.LowPart); + /* Check if this is the KnownDll hack */ + if (NoActualCheck) + { + /* Don't actually do it */ + Result = TRUE; + } + else + { + /* Verify the checksum */ + Result = LdrVerifyMappedImageMatchesChecksum(ViewBase, + FileStandardInfo.EndOfFile.LowPart, + FileStandardInfo.EndOfFile.LowPart); + } /* Check if a callback was supplied */ - if (Result && Callback) + if ((Result) && (Callback)) { /* Get the NT Header */ NtHeader = RtlImageNtHeader(ViewBase); @@ -847,7 +904,7 @@ LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle, NtClose(SectionHandle); /* Return status */ - return !Result ? STATUS_IMAGE_CHECKSUM_MISMATCH : Status; + return Result ? Status : STATUS_IMAGE_CHECKSUM_MISMATCH; } NTSTATUS @@ -988,9 +1045,14 @@ LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation, return LdrQueryProcessModuleInformationEx(0, 0, ModuleInformation, Size, ReturnedSize); } +/* + * @implemented + */ NTSTATUS NTAPI -LdrEnumerateLoadedModules(BOOLEAN ReservedFlag, PLDR_ENUM_CALLBACK EnumProc, PVOID Context) +LdrEnumerateLoadedModules(IN BOOLEAN ReservedFlag, + IN PLDR_ENUM_CALLBACK EnumProc, + IN PVOID Context) { PLIST_ENTRY ListHead, ListEntry; PLDR_DATA_TABLE_ENTRY LdrEntry; @@ -999,7 +1061,7 @@ LdrEnumerateLoadedModules(BOOLEAN ReservedFlag, PLDR_ENUM_CALLBACK EnumProc, PVO BOOLEAN Stop = FALSE; /* Check parameters */ - if (ReservedFlag || !EnumProc) return STATUS_INVALID_PARAMETER; + if ((ReservedFlag) || !(EnumProc)) return STATUS_INVALID_PARAMETER; /* Acquire the loader lock */ Status = LdrLockLoaderLock(0, NULL, &Cookie); @@ -1050,4 +1112,439 @@ LdrEnumerateLoadedModules(BOOLEAN ReservedFlag, PLDR_ENUM_CALLBACK EnumProc, PVO return STATUS_SUCCESS; } +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress) +{ + PLDR_DATA_TABLE_ENTRY LdrEntry; + NTSTATUS Status; + BOOLEAN LockHeld; + ULONG_PTR Cookie; + DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress); + + /* Don't do it during shutdown */ + if (LdrpShutdownInProgress) return STATUS_SUCCESS; + + /* Check if we should grab the lock */ + LockHeld = FALSE; + if (!LdrpInLdrInit) + { + /* Grab the lock */ + Status = LdrLockLoaderLock(0, NULL, &Cookie); + if (!NT_SUCCESS(Status)) return Status; + LockHeld = TRUE; + } + + /* Make sure the DLL is valid and get its entry */ + Status = STATUS_DLL_NOT_FOUND; + if (LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry)) + { + /* Get if it has a TLS slot */ + if (!LdrEntry->TlsIndex) + { + /* It doesn't, so you're allowed to call this */ + LdrEntry->Flags |= LDRP_DONT_CALL_FOR_THREADS; + Status = STATUS_SUCCESS; + } + } + + /* Check if the lock was held */ + if (LockHeld) + { + /* Release it */ + LdrUnlockLoaderLock(LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + } + + /* Return the status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrAddRefDll(IN ULONG Flags, + IN PVOID BaseAddress) +{ + PLDR_DATA_TABLE_ENTRY LdrEntry; + NTSTATUS Status = STATUS_SUCCESS; + ULONG Cookie; + BOOLEAN Locked = FALSE; + + /* Check for invalid flags */ + if (Flags & ~(LDR_ADDREF_DLL_PIN)) + { + /* Fail with invalid parameter status if so */ + Status = STATUS_INVALID_PARAMETER; + goto quickie; + } + + /* Acquire the loader lock if not in init phase */ + if (!LdrpInLdrInit) + { + /* Acquire the lock */ + Status = LdrLockLoaderLock(0, NULL, &Cookie); + if (!NT_SUCCESS(Status)) goto quickie; + Locked = TRUE; + } + + /* Get this module's data table entry */ + if (LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry)) + { + if (!LdrEntry) + { + /* Shouldn't happen */ + Status = STATUS_INTERNAL_ERROR; + goto quickie; + } + + /* If this is not a pinned module */ + if (LdrEntry->LoadCount != 0xFFFF) + { + /* Update its load count */ + if (Flags & LDR_ADDREF_DLL_PIN) + { + /* Pin it by setting load count to -1 */ + LdrEntry->LoadCount = 0xFFFF; + LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_PIN); + } + else + { + /* Increase its load count by one */ + LdrEntry->LoadCount++; + LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT); + } + + /* Clear load in progress */ + LdrpClearLoadInProgress(); + } + } + else + { + /* There was an error getting this module's handle, return invalid param status */ + Status = STATUS_INVALID_PARAMETER; + } + +quickie: + /* Check for error case */ + if (!NT_SUCCESS(Status)) + { + /* Print debug information */ + if ((ShowSnaps) || ((Status != STATUS_NO_SUCH_FILE) && + (Status != STATUS_DLL_NOT_FOUND) && + (Status != STATUS_OBJECT_NAME_NOT_FOUND))) + { + DPRINT1("LDR: LdrAddRefDll(%p) 0x%08lx\n", BaseAddress); + } + } + + /* Release the lock if needed */ + if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +LdrUnloadDll(IN PVOID BaseAddress) +{ + NTSTATUS Status = STATUS_SUCCESS; + PPEB Peb = NtCurrentPeb(); + PLDR_DATA_TABLE_ENTRY LdrEntry, CurrentEntry; + PVOID EntryPoint; + PLIST_ENTRY NextEntry; + LIST_ENTRY UnloadList; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; + PVOID CorImageData; + ULONG ComSectionSize; + + /* Get the LDR Lock */ + if (!LdrpInLdrInit) RtlEnterCriticalSection(Peb->LoaderLock); + + /* Increase the unload count */ + LdrpActiveUnloadCount++; + + /* Skip unload */ + if (LdrpShutdownInProgress) goto Quickie; + + /* Make sure the DLL is valid and get its entry */ + if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry)) + { + Status = STATUS_DLL_NOT_FOUND; + goto Quickie; + } + + /* Check the current Load Count */ + if (LdrEntry->LoadCount != 0xFFFF) + { + /* Decrease it */ + LdrEntry->LoadCount--; + + /* If it's a dll */ + if (LdrEntry->Flags & LDRP_IMAGE_DLL) + { + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrEntry->EntryPointActivationContext); + + /* Update the load count */ + LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_DEREFCOUNT); + + /* Release the context */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + } + else + { + /* The DLL is locked */ + goto Quickie; + } + + /* Show debug message */ + if (ShowSnaps) DPRINT1("LDR: UNINIT LIST\n"); + + /* Check if this is our only unload and initialize the list if so */ + if (LdrpActiveUnloadCount == 1) InitializeListHead(&LdrpUnloadHead); + + /* Loop the modules to build the list */ + NextEntry = Peb->Ldr->InInitializationOrderModuleList.Blink; + while (NextEntry != &Peb->Ldr->InInitializationOrderModuleList) + { + /* Get the entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InInitializationOrderModuleList); + NextEntry = NextEntry->Blink; + + /* Remove flag */ + LdrEntry->Flags &= ~LDRP_UNLOAD_IN_PROGRESS; + + /* If the load count is now 0 */ + if (!LdrEntry->LoadCount) + { + /* Show message */ + if (ShowSnaps) + { + DPRINT1("(%d) [%ws] %ws (%lx) deinit %lx\n", + LdrpActiveUnloadCount, + LdrEntry->BaseDllName.Buffer, + LdrEntry->FullDllName.Buffer, + (ULONG)LdrEntry->LoadCount, + LdrEntry->EntryPoint); + } + + /* FIXME: Call Shim Engine and notify */ + + /* Unlink it */ + CurrentEntry = LdrEntry; + RemoveEntryList(&CurrentEntry->InInitializationOrderModuleList); + RemoveEntryList(&CurrentEntry->InMemoryOrderModuleList); + RemoveEntryList(&CurrentEntry->HashLinks); + + /* If there's more then one active unload */ + if (LdrpActiveUnloadCount > 1) + { + /* Flush the cached DLL handle and clear the list */ + LdrpLoadedDllHandleCache = NULL; + CurrentEntry->InMemoryOrderModuleList.Flink = NULL; + } + + /* Add the entry on the unload list */ + InsertTailList(&LdrpUnloadHead, &CurrentEntry->HashLinks); + } + } + + /* Only call the entrypoints once */ + if (LdrpActiveUnloadCount > 1) goto Quickie; + + /* Now loop the unload list and create our own */ + InitializeListHead(&UnloadList); + CurrentEntry = NULL; + NextEntry = LdrpUnloadHead.Flink; + while (NextEntry != &LdrpUnloadHead) + { + /* If we have an active entry */ + if (CurrentEntry) + { + /* Remove it */ + RemoveEntryList(&CurrentEntry->InLoadOrderLinks); + CurrentEntry = NULL; + + /* Reset list pointers */ + NextEntry = LdrpUnloadHead.Flink; + if (NextEntry == &LdrpUnloadHead) break; + } + + /* Get the current entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks); + + /* FIXME: Log the Unload Event */ + //LdrpRecordUnloadEvent(LdrEntry); + + /* Set the entry and clear it from the list */ + CurrentEntry = LdrEntry; + LdrpLoadedDllHandleCache = NULL; + CurrentEntry->InMemoryOrderModuleList.Flink = NULL; + + /* Move it from the global to the local list */ + RemoveEntryList(&CurrentEntry->HashLinks); + InsertTailList(&UnloadList, &CurrentEntry->HashLinks); + + /* Get the entrypoint */ + EntryPoint = LdrEntry->EntryPoint; + + /* Check if we should call it */ + if ((EntryPoint) && (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED)) + { + /* Show message */ + if (ShowSnaps) + { + DPRINT1("LDR: Calling deinit %lx\n", EntryPoint); + } + + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrEntry->EntryPointActivationContext); + + /* Call the entrypoint */ + LdrpCallInitRoutine(LdrEntry->EntryPoint, + LdrEntry->DllBase, + DLL_PROCESS_DETACH, + NULL); + + /* Release the context */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); + } + + /* Remove it from the list */ + RemoveEntryList(&CurrentEntry->InLoadOrderLinks); + CurrentEntry = NULL; + NextEntry = LdrpUnloadHead.Flink; + } + + /* Now loop our local list */ + NextEntry = UnloadList.Flink; + while (NextEntry != &UnloadList) + { + /* Get the entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks); + NextEntry = NextEntry->Flink; + CurrentEntry = LdrEntry; + + /* Notify Application Verifier */ + if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK) + { + DPRINT1("We don't support Application Verifier yet\n"); + } + + /* Show message */ + if (ShowSnaps) + { + DPRINT1("LDR: Unmapping [%ws]\n", LdrEntry->BaseDllName.Buffer); + } + + /* Check if this is a .NET executable */ + CorImageData = RtlImageDirectoryEntryToData(LdrEntry->DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, + &ComSectionSize); + if (CorImageData) + { + /* FIXME */ + DPRINT1(".NET Images are not supported yet\n"); + } + + /* Check if we should unmap*/ + if (!(CurrentEntry->Flags & LDR_COR_OWNS_UNMAP)) + { + /* Unmap the DLL */ + Status = NtUnmapViewOfSection(NtCurrentProcess(), + CurrentEntry->DllBase); + ASSERT(NT_SUCCESS(Status)); + } + + /* Unload the alternate resource module, if any */ + LdrUnloadAlternateResourceModule(CurrentEntry->DllBase); + + /* FIXME: Send shutdown notification */ + //LdrpSendDllNotifications(CurrentEntry, 2, LdrpShutdownInProgress); + + /* Check if a Hotpatch is active */ + if (LdrEntry->PatchInformation) + { + /* FIXME */ + DPRINT1("We don't support Hotpatching yet\n"); + } + + /* Deallocate the Entry */ + LdrpFinalizeAndDeallocateDataTableEntry(CurrentEntry); + + /* If this is the cached entry, invalidate it */ + if (LdrpGetModuleHandleCache == CurrentEntry) + { + LdrpGetModuleHandleCache = NULL; + } + } + +Quickie: + /* Decrease unload count */ + LdrpActiveUnloadCount--; + if (!LdrpInLdrInit) RtlLeaveCriticalSection(Peb->LoaderLock); + + /* Return to caller */ + return Status; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +RtlDllShutdownInProgress(VOID) +{ + /* Return the internal global */ + return LdrpShutdownInProgress; +} + +/* + * @implemented + */ +PIMAGE_BASE_RELOCATION +NTAPI +LdrProcessRelocationBlock(IN ULONG_PTR Address, + IN ULONG Count, + IN PUSHORT TypeOffset, + IN LONG_PTR Delta) +{ + return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta); +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +LdrUnloadAlternateResourceModule(IN PVOID BaseAddress) +{ + static BOOLEAN WarnedOnce = FALSE; + if (WarnedOnce == FALSE) { UNIMPLEMENTED; WarnedOnce = TRUE; } + return FALSE; +} + /* EOF */ diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c index fd0aa391f11..8bb2e40d219 100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c @@ -561,7 +561,7 @@ LdrpInitializeThread(IN PCONTEXT Context) if (!LdrpShutdownInProgress) { /* Call TLS */ - LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_ATTACH); + LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_ATTACH); } } @@ -571,7 +571,7 @@ LdrpInitializeThread(IN PCONTEXT Context) /* Call the Entrypoint */ DPRINT("%wZ - Calling entry point at %x for thread attaching\n", &LdrEntry->BaseDllName, LdrEntry->EntryPoint); - LdrpCallDllEntry(LdrEntry->EntryPoint, + LdrpCallInitRoutine(LdrEntry->EntryPoint, LdrEntry->DllBase, DLL_THREAD_ATTACH, NULL); @@ -600,7 +600,7 @@ LdrpInitializeThread(IN PCONTEXT Context) LdrpImageEntry->EntryPointActivationContext); /* Do TLS callbacks */ - LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_ATTACH); + LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_ATTACH); /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -796,7 +796,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) if (LdrEntry->TlsIndex && Context) { /* Call TLS */ - LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_ATTACH); + LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_ATTACH); } /* Call the Entrypoint */ @@ -805,7 +805,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) DPRINT1("%wZ - Calling entry point at %p for DLL_PROCESS_ATTACH\n", &LdrEntry->BaseDllName, EntryPoint); } - DllStatus = LdrpCallDllEntry(EntryPoint, + DllStatus = LdrpCallInitRoutine(EntryPoint, LdrEntry->DllBase, DLL_PROCESS_ATTACH, Context); @@ -859,7 +859,7 @@ LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL) LdrpImageEntry->EntryPointActivationContext); /* Do TLS callbacks */ - LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH); + LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_ATTACH); /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -956,13 +956,13 @@ LdrShutdownProcess(VOID) if (LdrEntry->TlsIndex) { /* Call TLS */ - LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_DETACH); + LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_PROCESS_DETACH); } /* Call the Entrypoint */ DPRINT("%wZ - Calling entry point at %x for thread detaching\n", &LdrEntry->BaseDllName, LdrEntry->EntryPoint); - LdrpCallDllEntry(EntryPoint, + LdrpCallInitRoutine(EntryPoint, LdrEntry->DllBase, DLL_PROCESS_DETACH, (PVOID)1); @@ -986,7 +986,7 @@ LdrShutdownProcess(VOID) LdrpImageEntry->EntryPointActivationContext); /* Do TLS callbacks */ - LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_DETACH); + LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_PROCESS_DETACH); /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -1067,7 +1067,7 @@ LdrShutdownThread(VOID) if (!LdrpShutdownInProgress) { /* Call TLS */ - LdrpTlsCallback(LdrEntry->DllBase, DLL_THREAD_DETACH); + LdrpCallTlsInitializers(LdrEntry->DllBase, DLL_THREAD_DETACH); } } @@ -1077,7 +1077,7 @@ LdrShutdownThread(VOID) /* Call the Entrypoint */ DPRINT("%wZ - Calling entry point at %x for thread detaching\n", &LdrEntry->BaseDllName, LdrEntry->EntryPoint); - LdrpCallDllEntry(EntryPoint, + LdrpCallInitRoutine(EntryPoint, LdrEntry->DllBase, DLL_THREAD_DETACH, NULL); @@ -1103,7 +1103,7 @@ LdrShutdownThread(VOID) LdrpImageEntry->EntryPointActivationContext); /* Do TLS callbacks */ - LdrpTlsCallback(Peb->ImageBaseAddress, DLL_THREAD_DETACH); + LdrpCallTlsInitializers(Peb->ImageBaseAddress, DLL_THREAD_DETACH); /* Deactivate the ActCtx */ RtlDeactivateActivationContextUnsafeFast(&ActCtx); @@ -1358,6 +1358,7 @@ LdrpInitializeProcess(IN PCONTEXT Context, PLDR_DATA_TABLE_ENTRY NtLdrEntry; PWCHAR Current; ULONG ExecuteOptions = 0; + PVOID ViewBase; /* Set a NULL SEH Filter */ RtlSetUnhandledExceptionFilter(NULL); @@ -1624,16 +1625,10 @@ LdrpInitializeProcess(IN PCONTEXT Context, &ObjectAttributes); /* Check if it exists */ - if (!NT_SUCCESS(Status)) - { - /* It doesn't, so assume System32 */ - LdrpKnownDllObjectDirectory = NULL; - RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); - LdrpKnownDllPath.Length -= sizeof(WCHAR); - } - else + if (NT_SUCCESS(Status)) { /* Open the Known DLLs Path */ + RtlInitUnicodeString(&KnownDllString, L"KnownDllPath"); InitializeObjectAttributes(&ObjectAttributes, &KnownDllString, OBJ_CASE_INSENSITIVE, @@ -1658,6 +1653,15 @@ LdrpInitializeProcess(IN PCONTEXT Context, } } + /* Check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Aassume System32 */ + LdrpKnownDllObjectDirectory = NULL; + RtlInitUnicodeString(&LdrpKnownDllPath, StringBuffer); + LdrpKnownDllPath.Length -= sizeof(WCHAR); + } + /* If we have process parameters, get the default path and current path */ if (ProcessParameters) { @@ -1855,13 +1859,37 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Check if relocation is needed */ if (Peb->ImageBaseAddress != (PVOID)NtHeader->OptionalHeader.ImageBase) { - DPRINT("LDR: Performing relocations\n"); - Status = LdrPerformRelocations(NtHeader, Peb->ImageBaseAddress); + DPRINT1("LDR: Performing EXE relocation\n"); + + /* Change the protection to prepare for relocation */ + ViewBase = Peb->ImageBaseAddress; + Status = LdrpSetProtection(ViewBase, FALSE); + if (!NT_SUCCESS(Status)) return Status; + + /* Do the relocation */ + Status = LdrRelocateImageWithBias(ViewBase, + 0LL, + NULL, + STATUS_SUCCESS, + STATUS_CONFLICTING_ADDRESSES, + STATUS_INVALID_IMAGE_FORMAT); if (!NT_SUCCESS(Status)) { - DPRINT1("LdrPerformRelocations() failed\n"); + DPRINT1("LdrRelocateImageWithBias() failed\n"); + return Status; + } + + /* Check if a start context was provided */ + if (Context) + { + DPRINT1("WARNING: Relocated EXE Context"); + UNIMPLEMENTED; // We should support this return STATUS_INVALID_IMAGE_FORMAT; } + + /* Restore the protection */ + Status = LdrpSetProtection(ViewBase, TRUE); + if (!NT_SUCCESS(Status)) return Status; } /* Lock the DLLs */ diff --git a/dll/ntdll/ldr/ldrpe.c b/dll/ntdll/ldr/ldrpe.c index 41694d37e96..aa3ef415d4b 100644 --- a/dll/ntdll/ldr/ldrpe.c +++ b/dll/ntdll/ldr/ldrpe.c @@ -13,20 +13,9 @@ #include /* GLOBALS *******************************************************************/ -ULONG LdrpFatalHardErrorCount; -PVOID LdrpManifestProberRoutine; - -/* PROTOTYPES ****************************************************************/ - -#define IMAGE_REL_BASED_HIGH3ADJ 11 -NTSTATUS -NTAPI -LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, - IN LPSTR ImportName, - IN PVOID DllBase, - OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry, - OUT PBOOLEAN Existing); +PVOID LdrpManifestProberRoutine; +ULONG LdrpNormalSnap; /* FUNCTIONS *****************************************************************/ @@ -37,21 +26,15 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, IN PIMAGE_IMPORT_DESCRIPTOR IatEntry, IN BOOLEAN EntriesValid) { - PIMAGE_EXPORT_DIRECTORY ExportDirectory; - ULONG ExportSize; PVOID Iat; - SIZE_T ImportSize; - ULONG IatSize; - //PPEB Peb = NtCurrentPeb(); NTSTATUS Status; PIMAGE_THUNK_DATA OriginalThunk, FirstThunk; - LPSTR ImportName; - ULONG ForwarderChain; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER SectionHeader; - ULONG i, Rva; - ULONG OldProtect; - + PIMAGE_EXPORT_DIRECTORY ExportDirectory; + LPSTR ImportName; + ULONG ForwarderChain, i, Rva, OldProtect, IatSize, ExportSize; + SIZE_T ImportSize; DPRINT("LdrpSnapIAT(%wZ %wZ %p %d)\n", &ExportLdrEntry->BaseDllName, &ImportLdrEntry->BaseDllName, IatEntry, EntriesValid); /* Get export directory */ @@ -61,7 +44,13 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, &ExportSize); /* Make sure it has one */ - if (!ExportDirectory) return STATUS_INVALID_IMAGE_FORMAT; + if (!ExportDirectory) + { + /* Fail */ + DbgPrint("LDR: %wZ doesn't contain an EXPORT table\n", + &ExportLdrEntry->BaseDllName); + return STATUS_INVALID_IMAGE_FORMAT; + } /* Get the IAT */ Iat = RtlImageDirectoryEntryToData(ImportLdrEntry->DllBase, @@ -75,6 +64,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, { /* Get the NT Header and the first section */ NtHeader = RtlImageNtHeader(ImportLdrEntry->DllBase); + if (!NtHeader) return STATUS_INVALID_IMAGE_FORMAT; SectionHeader = IMAGE_FIRST_SECTION(NtHeader); /* Get the RVA of the import directory */ @@ -99,8 +89,7 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, IatSize = SectionHeader->Misc.VirtualSize; /* Deal with Watcom and other retarded compilers */ - if (!IatSize) - IatSize = SectionHeader->SizeOfRawData; + if (!IatSize) IatSize = SectionHeader->SizeOfRawData; /* Found it, get out */ break; @@ -112,7 +101,14 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, } /* If we still don't have an IAT, that's bad */ - if (!Iat) return STATUS_INVALID_IMAGE_FORMAT; + if (!Iat) + { + /* Fail */ + DbgPrint("LDR: Unable to unprotect IAT for %wZ (Image Base %p)\n", + &ImportLdrEntry->BaseDllName, + ImportLdrEntry->DllBase); + return STATUS_INVALID_IMAGE_FORMAT; + } /* Set the right size */ ImportSize = IatSize; @@ -124,7 +120,14 @@ LdrpSnapIAT(IN PLDR_DATA_TABLE_ENTRY ExportLdrEntry, &ImportSize, PAGE_READWRITE, &OldProtect); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + /* Fail */ + DbgPrint("LDR: Unable to unprotect IAT for %wZ (Status %x)\n", + &ImportLdrEntry->BaseDllName, + Status); + return Status; + } /* Check if the Thunks are already valid */ if (EntriesValid) @@ -410,6 +413,7 @@ LdrpHandleOneNewFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, if (Stale) { /* It was, so find the IAT entry for it */ + ++LdrpNormalSnap; ImportEntry = RtlImageDirectoryEntryToData(LdrEntry->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, @@ -511,22 +515,21 @@ NTSTATUS NTAPI LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, IN PLDR_DATA_TABLE_ENTRY LdrEntry, - IN PIMAGE_IMPORT_DESCRIPTOR ImportEntry) + IN PIMAGE_IMPORT_DESCRIPTOR *ImportEntry) { - //ULONG IatSize, i; LPSTR ImportName; NTSTATUS Status; - BOOLEAN AlreadyLoaded = FALSE, StaticEntriesValid = FALSE, SkipSnap = FALSE; + BOOLEAN AlreadyLoaded = FALSE; PLDR_DATA_TABLE_ENTRY DllLdrEntry; PIMAGE_THUNK_DATA FirstThunk; PPEB Peb = NtCurrentPeb(); /* Get the import name's VA */ - ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name); + ImportName = (LPSTR)((ULONG_PTR)LdrEntry->DllBase + (*ImportEntry)->Name); /* Get the first thunk */ FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase + - ImportEntry->FirstThunk); + (*ImportEntry)->FirstThunk); /* Make sure it's valid */ if (!FirstThunk->u1.Function) goto SkipEntry; @@ -545,7 +548,20 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, LdrEntry->DllBase, &DllLdrEntry, &AlreadyLoaded); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + /* Fail */ + if (ShowSnaps) + { + DbgPrint("LDR: LdrpWalkImportTable - LdrpLoadImportModule failed " + "on import %s with status %x\n", + ImportName, + Status); + } + + /* Return */ + return Status; + } /* Show debug message */ if (ShowSnaps) @@ -555,41 +571,8 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, ImportName); } - /* Check if the image was bound when compiled */ - if (ImportEntry->OriginalFirstThunk) - { - /* It was, so check if the static IAT entries are still valid */ - if ((ImportEntry->TimeDateStamp) && - (ImportEntry->TimeDateStamp == DllLdrEntry->TimeDateStamp) && - (!(DllLdrEntry->Flags & LDRP_IMAGE_NOT_AT_BASE))) - { - /* Show debug message */ - if (ShowSnaps) - { - DPRINT1("LDR: Snap bypass %s from %wZ\n", - ImportName, - &LdrEntry->BaseDllName); - } - - /* - * They are still valid, so we can skip snapping them. - * Additionally, if we have no forwarders, we are totally - * done. - */ - if (ImportEntry->ForwarderChain == -1) - { - /* Totally skip LdrpSnapIAT */ - SkipSnap = TRUE; - } - else - { - /* Set this so LdrpSnapIAT will only do forwarders */ - StaticEntriesValid = TRUE; - } - } - } - /* Check if it wasn't already loaded */ + ++LdrpNormalSnap; if (!AlreadyLoaded) { /* Add the DLL to our list */ @@ -597,18 +580,25 @@ LdrpHandleOneOldFormatImportDescriptor(IN LPWSTR DllPath OPTIONAL, &DllLdrEntry->InInitializationOrderModuleList); } - /* Check if we should snap at all */ - if (!SkipSnap) + /* Now snap the IAT Entry */ + Status = LdrpSnapIAT(DllLdrEntry, LdrEntry, *ImportEntry, FALSE); + if (!NT_SUCCESS(Status)) { - /* Now snap the IAT Entry */ - Status = LdrpSnapIAT(DllLdrEntry, - LdrEntry, - ImportEntry, - StaticEntriesValid); - if (!NT_SUCCESS(Status)) return Status; + /* Fail */ + if (ShowSnaps) + { + DbgPrint("LDR: LdrpWalkImportTable - LdrpSnapIAT #2 failed with " + "status %x\n", + Status); + } + + /* Return */ + return Status; } SkipEntry: + /* Move on */ + (*ImportEntry)++; return STATUS_SUCCESS; } @@ -621,34 +611,31 @@ LdrpHandleOldFormatImportDescriptors(IN LPWSTR DllPath OPTIONAL, NTSTATUS Status; /* Check for Name and Thunk */ - while (ImportEntry->Name && ImportEntry->FirstThunk) + while ((ImportEntry->Name) && (ImportEntry->FirstThunk)) { /* Parse this descriptor */ Status = LdrpHandleOneOldFormatImportDescriptor(DllPath, LdrEntry, - ImportEntry); + &ImportEntry); if (!NT_SUCCESS(Status)) return Status; - - /* Move to the next entry */ - ImportEntry++; } /* Done */ return STATUS_SUCCESS; } -USHORT NTAPI -LdrpNameToOrdinal(LPSTR ImportName, - ULONG NumberOfNames, - PVOID ExportBase, - PULONG NameTable, - PUSHORT OrdinalTable) +USHORT +NTAPI +LdrpNameToOrdinal(IN LPSTR ImportName, + IN ULONG NumberOfNames, + IN PVOID ExportBase, + IN PULONG NameTable, + IN PUSHORT OrdinalTable) { - ULONG Start, End, Next; - LONG CmpResult; + LONG Start, End, Next, CmpResult; /* Use classical binary search to find the ordinal */ - Start = 0; + Start = Next = 0; End = NumberOfNames - 1; while (End >= Start) { @@ -663,9 +650,13 @@ LdrpNameToOrdinal(LPSTR ImportName, /* We didn't find, update our range then */ if (CmpResult < 0) + { End = Next - 1; + } else if (CmpResult > 0) + { Start = Next + 1; + } } /* If end is before start, then the search failed */ @@ -686,13 +677,12 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry = NULL; PIMAGE_IMPORT_DESCRIPTOR ImportEntry; ULONG BoundSize, IatSize; - DPRINT("LdrpWalkImportDescriptor('%S' %x)\n", DllPath, LdrEntry); /* Set up the Act Ctx */ + RtlZeroMemory(&ActCtx, sizeof(ActCtx)); ActCtx.Size = sizeof(ActCtx); - ActCtx.Format = 1; - RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; /* Check if we have a manifest prober routine */ if (LdrpManifestProberRoutine) @@ -705,7 +695,16 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, /* Get the Active ActCtx */ Status = RtlGetActiveActivationContext(&LdrEntry->EntryPointActivationContext); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + /* Exit */ + DbgPrintEx(51, // DPFLTR_SXS_ID + DPFLTR_WARNING_LEVEL, + "LDR: RtlGetActiveActivationContext() failed; ntstatus = " + "0x%08lx\n", + Status); + return Status; + } /* Activate the ActCtx */ RtlActivateActivationContextUnsafeFast(&ActCtx, @@ -728,7 +727,7 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, &IatSize); /* Check if we got at least one */ - if (BoundEntry || ImportEntry) + if ((BoundEntry) || (ImportEntry)) { /* Do we have a Bound IAT */ if (BoundEntry) @@ -782,6 +781,7 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, return Status; } +/* FIXME: This function is missing SxS support and has wrong prototype */ NTSTATUS NTAPI LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, diff --git a/dll/ntdll/ldr/ldrutils.c b/dll/ntdll/ldr/ldrutils.c index b3c4dcebc1c..e3443125afa 100644 --- a/dll/ntdll/ldr/ldrutils.c +++ b/dll/ntdll/ldr/ldrutils.c @@ -14,27 +14,90 @@ #include /* GLOBALS *******************************************************************/ -#define IMAGE_DLLCHARACTERISTICS_WX86_DLL 0x1000 -LIST_ENTRY LdrpUnloadHead; -PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache; -PLDR_DATA_TABLE_ENTRY LdrpGetModuleHandleCache; - -#define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1)) +PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache, LdrpGetModuleHandleCache; +BOOLEAN g_ShimsEnabled; /* FUNCTIONS *****************************************************************/ +NTSTATUS +NTAPI +LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut, + IN ULONG Length) +{ + /* Sanity checks */ + ASSERT(StringOut); + ASSERT(Length <= UNICODE_STRING_MAX_BYTES); + + /* Assume failure */ + StringOut->Length = 0; + + /* Make sure it's not mis-aligned */ + if (Length & 1) + { + /* Fail */ + StringOut->Buffer = NULL; + StringOut->MaximumLength = 0; + return STATUS_INVALID_PARAMETER; + } + + /* Allocate the string*/ + StringOut->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + StringOut->Length + sizeof(WCHAR)); + if (!StringOut->Buffer) + { + /* Fail */ + StringOut->MaximumLength = 0; + return STATUS_NO_MEMORY; + } + + /* Null-terminate it */ + StringOut->Buffer[StringOut->Length / sizeof(WCHAR)] = UNICODE_NULL; + + /* Check if this is a maximum-sized string */ + if (StringOut->Length != UNICODE_STRING_MAX_BYTES) + { + /* It's not, so set the maximum length to be one char more */ + StringOut->MaximumLength = StringOut->Length + sizeof(UNICODE_NULL); + } + else + { + /* The length is already the maximum possible */ + StringOut->MaximumLength = UNICODE_STRING_MAX_BYTES; + } + + /* Return success */ + return STATUS_SUCCESS; +} + +VOID +NTAPI +LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn) +{ + ASSERT(StringIn != NULL); + + /* If Buffer is not NULL - free it */ + if (StringIn->Buffer) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, StringIn->Buffer); + } + + /* Zero it out */ + RtlInitEmptyUnicodeString(StringIn, NULL, 0); +} BOOLEAN NTAPI -LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, - PVOID BaseAddress, - ULONG Reason, - PVOID Context) +LdrpCallInitRoutine(IN PDLL_INIT_ROUTINE EntryPoint, + IN PVOID BaseAddress, + IN ULONG Reason, + IN PVOID Context) { /* Call the entry */ return EntryPoint(BaseAddress, Reason, Context); } +/* NOTE: This function is broken */ VOID NTAPI LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, @@ -42,8 +105,6 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, OUT PUNICODE_STRING UpdateString) { PIMAGE_BOUND_FORWARDER_REF NewImportForwarder; - - PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry; PIMAGE_IMPORT_DESCRIPTOR ImportEntry; PIMAGE_THUNK_DATA FirstThunk; @@ -106,7 +167,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, FALSE, &Entry)) { - if (Entry->LoadCount != -1) + if (Entry->LoadCount != 0xFFFF) { /* Perform the required action */ switch (Flags) @@ -118,7 +179,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, Entry->LoadCount--; break; case LDRP_UPDATE_PIN: - Entry->LoadCount = -1; + Entry->LoadCount = 0xFFFF; break; } @@ -150,7 +211,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, FALSE, &Entry)) { - if (Entry->LoadCount != -1) + if (Entry->LoadCount != 0xFFFF) { /* Perform the required action */ switch (Flags) @@ -162,7 +223,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, Entry->LoadCount--; break; case LDRP_UPDATE_PIN: - Entry->LoadCount = -1; + Entry->LoadCount = 0xFFFF; break; } @@ -219,7 +280,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, FALSE, &Entry)) { - if (Entry->LoadCount != -1) + if (Entry->LoadCount != 0xFFFF) { /* Perform the required action */ switch (Flags) @@ -231,7 +292,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, Entry->LoadCount--; break; case LDRP_UPDATE_PIN: - Entry->LoadCount = -1; + Entry->LoadCount = 0xFFFF; break; } @@ -261,18 +322,15 @@ LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry, WCHAR Buffer[MAX_PATH]; UNICODE_STRING UpdateString; - /* Setup the string */ - UpdateString.Buffer = Buffer; - UpdateString.Length = 0; - UpdateString.MaximumLength = sizeof(Buffer); - - /* Call the extended API */ + /* Setup the string and call the extended API */ + RtlInitEmptyUnicodeString(&UpdateString, Buffer, sizeof(Buffer)); LdrpUpdateLoadCount3(LdrEntry, Flags, &UpdateString); } VOID NTAPI -LdrpTlsCallback(PVOID BaseAddress, ULONG Reason) +LdrpCallTlsInitializers(IN PVOID BaseAddress, + IN ULONG Reason) { PIMAGE_TLS_DIRECTORY TlsDirectory; PIMAGE_TLS_CALLBACK *Array, Callback; @@ -287,31 +345,39 @@ LdrpTlsCallback(PVOID BaseAddress, ULONG Reason) /* Protect against invalid pointers */ _SEH2_TRY { - /* Make sure it's valid and we have an array */ - if (TlsDirectory && (Array = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks)) + /* Make sure it's valid */ + if (TlsDirectory) { - /* Display debug */ - if (ShowSnaps) - { - DPRINT1("LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p\n", - BaseAddress, TlsDirectory, Array); - } - - /* Loop the array */ - while (*Array) + /* Get the array */ + Array = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks; + if (Array) { - /* Get the TLS Entrypoint */ - Callback = *Array++; - /* Display debug */ if (ShowSnaps) { - DPRINT1("LDR: Calling Tls Callback Imagebase %p Function %p\n", - BaseAddress, Callback); + DPRINT1("LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p\n", + BaseAddress, TlsDirectory, Array); } - /* Call it */ - LdrpCallDllEntry((PDLLMAIN_FUNC)Callback, BaseAddress, Reason, NULL); + /* Loop the array */ + while (*Array) + { + /* Get the TLS Entrypoint */ + Callback = *Array++; + + /* Display debug */ + if (ShowSnaps) + { + DPRINT1("LDR: Calling Tls Callback Imagebase %p Function %p\n", + BaseAddress, Callback); + } + + /* Call it */ + LdrpCallInitRoutine((PDLL_INIT_ROUTINE)Callback, + BaseAddress, + Reason, + NULL); + } } } } @@ -324,9 +390,10 @@ LdrpTlsCallback(PVOID BaseAddress, ULONG Reason) NTSTATUS NTAPI -LdrpCodeAuthzCheckDllAllowed(PUNICODE_STRING FullName, - HANDLE DllHandle) +LdrpCodeAuthzCheckDllAllowed(IN PUNICODE_STRING FullName, + IN HANDLE DllHandle) { + /* Not implemented */ return STATUS_SUCCESS; } @@ -436,7 +503,7 @@ LdrpCreateDllSection(IN PUNICODE_STRING FullName, /* Check for Safer restrictions */ if (DllCharacteristics && - !(*DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WX86_DLL)) + !(*DllCharacteristics & IMAGE_FILE_SYSTEM)) { /* Make sure it's executable */ Status = ZwQuerySection(*SectionHandle, @@ -446,10 +513,10 @@ LdrpCreateDllSection(IN PUNICODE_STRING FullName, NULL); if (NT_SUCCESS(Status)) { - /* Check if it's executable */ - if (SectionImageInfo.ImageContainsCode) + /* Bypass the check for .NET images */ + if (!(SectionImageInfo.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS)) { - /* It is, check safer */ + /* Check with Safer */ Status = LdrpCodeAuthzCheckDllAllowed(FullName, DllHandle); if (!NT_SUCCESS(Status) && (Status != STATUS_NOT_FOUND)) { @@ -459,21 +526,21 @@ LdrpCreateDllSection(IN PUNICODE_STRING FullName, DPRINT1("LDR: Loading of (%wZ) blocked by Winsafer\n", &FullName); } - } - else - { - /* We're fine, return normally */ - goto Quickie; + + /* Failure case, close section handle */ + NtClose(*SectionHandle); + *SectionHandle = NULL; } } } - - /* Failure case, close section handle */ - NtClose(*SectionHandle); - *SectionHandle = NULL; + else + { + /* Failure case, close section handle */ + NtClose(*SectionHandle); + *SectionHandle = NULL; + } } -Quickie: /* Close the file handle, we don't need it */ NtClose(FileHandle); @@ -481,6 +548,7 @@ Quickie: return Status; } +/* NOTE: This function is totally b0rked and doesn't handle the parameters/functionality it should */ BOOLEAN NTAPI LdrpResolveDllName(PWSTR DllPath, @@ -577,25 +645,25 @@ LdrpResolveDllName(PWSTR DllPath, PVOID NTAPI -LdrpFetchAddressOfEntryPoint(PVOID ImageBase) +LdrpFetchAddressOfEntryPoint(IN PVOID ImageBase) { PIMAGE_NT_HEADERS NtHeaders; - ULONG_PTR EntryPoint; + ULONG_PTR EntryPoint = 0; /* Get entry point offset from NT headers */ NtHeaders = RtlImageNtHeader(ImageBase); - EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint; - - /* If it's 0 - return so */ - if (!EntryPoint) return NULL; - - /* Add image base */ - EntryPoint += (ULONG_PTR)ImageBase; + if (NtHeaders) + { + /* Add image base */ + EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint; + if (EntryPoint) EntryPoint += (ULONG_PTR)ImageBase; + } - /* Return calculated pointer */ + /* Return calculated pointer (or zero in case of failure) */ return (PVOID)EntryPoint; } +/* NOTE: This function is broken, wrong number of parameters, no SxS, etc */ HANDLE NTAPI LdrpCheckForKnownDll(PWSTR DllName, @@ -702,31 +770,36 @@ LdrpSetProtection(PVOID ViewBase, /* Get the NT headers */ NtHeaders = RtlImageNtHeader(ViewBase); + if (!NtHeaders) return STATUS_INVALID_IMAGE_FORMAT; /* Compute address of the first section header */ - Section = (PIMAGE_SECTION_HEADER)( - (ULONG_PTR)NtHeaders + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + - NtHeaders->FileHeader.SizeOfOptionalHeader); + Section = IMAGE_FIRST_SECTION(NtHeaders); /* Go through all sections */ for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++) { - if (Section->SizeOfRawData && + /* Check for read-only non-zero section */ + if ((Section->SizeOfRawData) && !(Section->Characteristics & IMAGE_SCN_MEM_WRITE)) { - /* This section is not writable and has some size, so we need to change - its protection */ + /* Check if we are setting or restoring protection */ if (Restore) { /* Set it to either EXECUTE or READONLY */ if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) + { NewProtection = PAGE_EXECUTE; + } else + { NewProtection = PAGE_READONLY; + } /* Add PAGE_NOCACHE if needed */ if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) + { NewProtection |= PAGE_NOCACHE; + } } else { @@ -734,9 +807,9 @@ LdrpSetProtection(PVOID ViewBase, NewProtection = PAGE_READWRITE; } + /* Get the section VA */ SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress); SectionSize = Section->SizeOfRawData; - if (SectionSize) { /* Set protection */ @@ -745,7 +818,6 @@ LdrpSetProtection(PVOID ViewBase, &SectionSize, NewProtection, &OldProtection); - if (!NT_SUCCESS(Status)) return Status; } } @@ -756,10 +828,10 @@ LdrpSetProtection(PVOID ViewBase, /* Flush instruction cache if necessary */ if (Restore) ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0); - return STATUS_SUCCESS; } +/* NOTE: Not yet reviewed */ NTSTATUS NTAPI LdrpMapDll(IN PWSTR SearchPath OPTIONAL, @@ -878,7 +950,7 @@ SkipCheck: /* We couldn't resolve the name, is this a static load? */ if (Static) { - /* + /* * This is BAD! Static loads are CRITICAL. Bugcheck! * Initialize the strings for the error */ @@ -1275,11 +1347,12 @@ NTAPI LdrpAllocateDataTableEntry(IN PVOID BaseAddress) { PLDR_DATA_TABLE_ENTRY LdrEntry = NULL; - PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader(BaseAddress); + PIMAGE_NT_HEADERS NtHeader; + /* Make sure the header is valid */ + NtHeader = RtlImageNtHeader(BaseAddress); DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader); - /* Make sure the header is valid */ if (NtHeader) { /* Allocate an entry */ @@ -1294,6 +1367,7 @@ LdrpAllocateDataTableEntry(IN PVOID BaseAddress) LdrEntry->DllBase = BaseAddress; LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp; + LdrEntry->PatchInformation = NULL; } } @@ -1308,36 +1382,33 @@ LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr; ULONG i; - /* Get the Hash entry */ + /* Insert into hash table */ i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer[0]); - InsertTailList(&LdrpHashTable[i], &LdrEntry->HashLinks); + + /* Insert into other lists */ InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks); InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderModuleList); } VOID NTAPI -LdrpFinalizeAndDeallocateDataTableEntry(PLDR_DATA_TABLE_ENTRY Entry) +LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry) { + /* Sanity check */ ASSERT(Entry != NULL); - /* Release the activation context if it exists */ - if (Entry->EntryPointActivationContext) + /* Release the activation context if it exists and wasn't already released */ + if ((Entry->EntryPointActivationContext) && + (Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE)) { - /* Check if it wasn't already released */ - if ((HANDLE)Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE) - { - RtlReleaseActivationContext(Entry->EntryPointActivationContext); - - /* Mark it as invalid */ - Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE; - } + /* Mark it as invalid */ + RtlReleaseActivationContext(Entry->EntryPointActivationContext); + Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE; } /* Release the full dll name string */ - if (Entry->FullDllName.Buffer) - LdrpFreeUnicodeString(&Entry->FullDllName); + if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName); /* Finally free the entry's memory */ RtlFreeHeap(RtlGetProcessHeap(), 0, Entry); @@ -1352,7 +1423,8 @@ LdrpCheckForLoadedDllHandle(IN PVOID Base, PLIST_ENTRY ListHead, Next; /* Check the cache first */ - if (LdrpLoadedDllHandleCache && LdrpLoadedDllHandleCache->DllBase == Base) + if ((LdrpLoadedDllHandleCache) && + (LdrpLoadedDllHandleCache->DllBase == Base)) { /* We got lucky, return the cached entry */ *LdrEntry = LdrpLoadedDllHandleCache; @@ -1362,12 +1434,12 @@ LdrpCheckForLoadedDllHandle(IN PVOID Base, /* Time for a lookup */ ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; Next = ListHead->Flink; - while(Next != ListHead) + while (Next != ListHead) { /* Get the current entry */ - Current = CONTAINING_RECORD(Next, - LDR_DATA_TABLE_ENTRY, - InLoadOrderLinks); + Current = CONTAINING_RECORD(Next, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); /* Make sure it's not unloading and check for a match */ if ((Current->InMemoryOrderModuleList.Flink) && (Base == Current->DllBase)) @@ -1388,6 +1460,315 @@ LdrpCheckForLoadedDllHandle(IN PVOID Base, return FALSE; } +NTSTATUS +NTAPI +LdrpResolveFullName(IN PUNICODE_STRING OriginalName, + IN PUNICODE_STRING PathName, + IN PUNICODE_STRING FullPathName, + IN PUNICODE_STRING *ExpandedName) +{ + NTSTATUS Status = STATUS_SUCCESS; +// RTL_PATH_TYPE PathType; +// BOOLEAN InvalidName; + ULONG Length; + + /* Display debug output if snaps are on */ + if (ShowSnaps) + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Expanding full name of %wZ\n", + __FUNCTION__, + OriginalName); + } + + /* FIXME: Lock the PEB */ + //RtlEnterCriticalSection(&FastPebLock); +#if 0 + /* Get the path name */ + Length = RtlGetFullPathName_Ustr(OriginalName, + PathName->Length, + PathName->Buffer, + NULL, + &InvalidName, + &PathType); +#else + Length = 0; +#endif + if (!(Length) || (Length > UNICODE_STRING_MAX_BYTES)) + { + /* Fail */ + Status = STATUS_NAME_TOO_LONG; + goto Quickie; + } + + /* Check if the length hasn't changed */ + if (Length <= PathName->Length) + { + /* Return the same thing */ + *ExpandedName = PathName; + PathName->Length = (USHORT)Length; + goto Quickie; + } + + /* Sanity check */ + ASSERT(Length >= sizeof(WCHAR)); + + /* Allocate a string */ + Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Now get the full path again */ +#if 0 + Length = RtlGetFullPathName_Ustr(OriginalName, + FullPathName->Length, + FullPathName->Buffer, + NULL, + &InvalidName, + &PathType); +#else + Length = 0; +#endif + if (!(Length) || (Length > FullPathName->Length)) + { + /* Fail */ + LdrpFreeUnicodeString(FullPathName); + Status = STATUS_NAME_TOO_LONG; + } + else + { + /* Return the expanded name */ + *ExpandedName = FullPathName; + FullPathName->Length = (USHORT)Length; + } + +Quickie: + /* FIXME: Unlock the PEB */ + //RtlLeaveCriticalSection(&FastPebLock); + + /* Display debug output if snaps are on */ + if (ShowSnaps) + { + /* Check which output to use -- failure or success */ + if (NT_SUCCESS(Status)) + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Expanded to %wZ\n", + __FUNCTION__, + *ExpandedName); + } + else + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Failed to expand %wZ; 0x%08x\n", + __FUNCTION__, + OriginalName, + Status); + } + } + + /* If we failed, return NULL */ + if (!NT_SUCCESS(Status)) *ExpandedName = NULL; + + /* Return status */ + return Status; +} + +NTSTATUS +NTAPI +LdrpSearchPath(IN PWCHAR *SearchPath, + IN PWCHAR DllName, + IN PUNICODE_STRING PathName, + IN PUNICODE_STRING FullPathName, + IN PUNICODE_STRING *ExpandedName) +{ + BOOLEAN TryAgain = FALSE; + PWCHAR ActualSearchPath = *SearchPath; + UNICODE_STRING TestName; + NTSTATUS Status; + PWCHAR Buffer, BufEnd = NULL; + ULONG Length = 0; + WCHAR p; + PWCHAR pp; + + /* Check if we don't have a search path */ + if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer; + + /* Display debug output if snaps are on */ + if (ShowSnaps) + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Looking for %ws in %ws\n", + __FUNCTION__, + DllName, + *SearchPath); + } + + /* Check if we're dealing with a relative path */ + if (RtlDetermineDosPathNameType_U(DllName) != RtlPathTypeRelative) + { + /* Good, we're not. Create the name string */ + Status = RtlInitUnicodeStringEx(&TestName, DllName); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Make sure it exists */ + #if 0 + if (!RtlDoesFileExists_UstrEx(&TestName, TRUE)) + { + /* It doesn't, fail */ + Status = STATUS_DLL_NOT_FOUND; + goto Quickie; + } + #endif + + /* Resolve the full name */ + Status = LdrpResolveFullName(&TestName, + PathName, + FullPathName, + ExpandedName); + goto Quickie; + } + + /* FIXME: Handle relative case semicolon-lookup here */ + + /* Calculate length */ + Length += (ULONG)wcslen(DllName) + sizeof(UNICODE_NULL); + if (Length > UNICODE_STRING_MAX_CHARS) + { + /* Too long, fail */ + Status = STATUS_NAME_TOO_LONG; + goto Quickie; + } + + /* Allocate buffer */ + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR)); + if (!Buffer) + { + /* Fail */ + Status = STATUS_NO_MEMORY; + goto Quickie; + } + + /* FIXME: Setup TestName here */ + Status = STATUS_NOT_FOUND; + + /* Start loop */ + do + { + /* Get character */ + p = *ActualSearchPath; + if (!(p) && (p == ';')) + { + /* FIXME: We don't have a character, or is a semicolon.*/ + + /* Display debug output if snaps are on */ + if (ShowSnaps) + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Looking for %ws\n", + __FUNCTION__, + Buffer); + } + + /* Sanity check */ + TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR); + ASSERT(TestName.Length < TestName.MaximumLength); + + /* Check if the file exists */ + #if 0 + if (RtlDoesFileExists_UstrEx(&TestName, FALSE)) + #endif + { + /* It does. Reallocate the buffer */ + TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR); + TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(), + 0, + Buffer, + TestName.MaximumLength); + if (!TestName.Buffer) + { + /* Keep the old one */ + TestName.Buffer = Buffer; + } + else + { + /* Update buffer */ + Buffer = TestName.Buffer; + } + + /* Make sure we have a buffer at least */ + ASSERT(TestName.Buffer); + + /* Resolve the name */ + *SearchPath = ActualSearchPath++; + Status = LdrpResolveFullName(&TestName, + PathName, + FullPathName, + ExpandedName); + break; + } + + /* Update buffer end */ + BufEnd = Buffer; + + /* Update string position */ + pp = ActualSearchPath++; + } + else + { + /* Otherwise, write the character */ + *BufEnd = p; + BufEnd++; + } + + /* Check if the string is empty, meaning we're done */ + if (!(*ActualSearchPath)) TryAgain = TRUE; + + /* Advance in the string */ + ActualSearchPath++; + } while (!TryAgain); + + /* Check if we had a buffer and free it */ + if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + +Quickie: + /* Check if we got here through failure */ + if (!NT_SUCCESS(Status)) *ExpandedName = NULL; + + /* Display debug output if snaps are on */ + if (ShowSnaps) + { + /* Check which output to use -- failure or success */ + if (NT_SUCCESS(Status)) + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Returning %wZ\n", + __FUNCTION__, + *ExpandedName); + } + else + { + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Unable to locate %ws in %ws: 0x%08x\n", + __FUNCTION__, + DllName, + ActualSearchPath, + Status); + } + } + + /* Return status */ + return Status; +} + + +/* NOTE: This function is b0rked and in the process of being slowly unf*cked */ BOOLEAN NTAPI LdrpCheckForLoadedDll(IN PWSTR DllPath, @@ -1411,12 +1792,14 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath, PVOID ViewBase = NULL; SIZE_T ViewSize = 0; PIMAGE_NT_HEADERS NtHeader, NtHeader2; - DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath, DllName, Flag, RedirectedDll, LdrEntry); /* Check if a dll name was provided */ - if (!DllName->Buffer || !DllName->Buffer[0]) return FALSE; + if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE; + /* FIXME: Warning, "Flag" is used as magic instead of "Static" */ + /* FIXME: Warning, code does not support redirection at all */ + /* Look in the hash table if flag was set */ lookinhash: if (Flag) @@ -1453,7 +1836,7 @@ lookinhash: while (*wc) { /* Check for a slash in the current position*/ - if (*wc == L'\\' || *wc == L'/') + if ((*wc == L'\\') || (*wc == L'/')) { /* Found the slash, so dll name contains path */ FullPath = TRUE; @@ -1461,6 +1844,7 @@ lookinhash: /* Setup full dll name string */ FullDllName.Buffer = NameBuf; + /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */ Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer, DllName->Buffer, NULL, @@ -1469,7 +1853,7 @@ lookinhash: NULL); /* Check if that was successful */ - if (!Length || Length > sizeof(NameBuf) - sizeof(UNICODE_NULL)) + if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL)))) { if (ShowSnaps) { @@ -1496,18 +1880,22 @@ lookinhash: Flag = TRUE; goto lookinhash; } + + /* FIXME: Warning, activation context missing */ + /* NOTE: From here on down, everything looks good */ - /* Now go through the InLoadOrder module list */ + /* Loop the module list */ ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; ListEntry = ListHead->Flink; - while (ListEntry != ListHead) { - /* Get the containing record of the current entry and advance to the next one */ - CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + /* Get the current entry and advance to the next one */ + CurEntry = CONTAINING_RECORD(ListEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); ListEntry = ListEntry->Flink; - /* Check if it's already being unloaded */ + /* Check if it's being unloaded */ if (!CurEntry->InMemoryOrderModuleList.Flink) continue; /* Check if name matches */ @@ -1517,18 +1905,10 @@ lookinhash: { /* Found it */ *LdrEntry = CurEntry; - - /* Find activation context */ - Status = RtlFindActivationContextSectionString(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, DllName, NULL); - if (!NT_SUCCESS(Status)) - return FALSE; - else - return TRUE; + return TRUE; } } - /* The DLL was not found in the load order modules list. Perform a complex check */ - /* Convert given path to NT path */ if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer, &NtPathName, @@ -1545,7 +1925,6 @@ lookinhash: OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenFile(&FileHandle, SYNCHRONIZE | FILE_EXECUTE, &ObjectAttributes, @@ -1561,7 +1940,9 @@ lookinhash: /* Create a section for this file */ Status = NtCreateSection(&SectionHandle, - SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE, + SECTION_MAP_READ | + SECTION_MAP_EXECUTE | + SECTION_MAP_WRITE, NULL, NULL, PAGE_EXECUTE, @@ -1585,6 +1966,7 @@ lookinhash: ViewShare, 0, PAGE_EXECUTE); + /* Close section handle */ NtClose(SectionHandle); @@ -1592,52 +1974,51 @@ lookinhash: if (!NT_SUCCESS(Status)) return FALSE; /* Get pointer to the NT header of this section */ - NtHeader = RtlImageNtHeader(ViewBase); - if (!NtHeader) + Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader); + if (!(NT_SUCCESS(Status)) || !(NtHeader)) { /* Unmap the section and fail */ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); return FALSE; } - /* Go through the list of modules */ + /* Go through the list of modules again */ ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; ListEntry = ListHead->Flink; - while (ListEntry != ListHead) { - CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + /* Get the current entry and advance to the next one */ + CurEntry = CONTAINING_RECORD(ListEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); ListEntry = ListEntry->Flink; - /* Check if it's already being unloaded */ + /* Check if it's in the process of being unloaded */ if (!CurEntry->InMemoryOrderModuleList.Flink) continue; - + + /* The header is untrusted, use SEH */ _SEH2_TRY { /* Check if timedate stamp and sizes match */ - if (CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp && - CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage) + if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) && + (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage)) { /* Time, date and size match. Let's compare their headers */ NtHeader2 = RtlImageNtHeader(CurEntry->DllBase); - if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS))) { /* Headers match too! Finally ask the kernel to compare mapped files */ Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase); - if (!NT_SUCCESS(Status)) { + /* Almost identical, but not quite, keep trying */ _SEH2_YIELD(continue;) } else { - /* This is our entry! */ + /* This is our entry!, unmap and return success */ *LdrEntry = CurEntry; - - /* Unmap the section */ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); - _SEH2_YIELD(return TRUE;) } } @@ -1650,9 +2031,8 @@ lookinhash: _SEH2_END; } - /* Unmap the section */ + /* Unmap the section and fail */ NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); - return FALSE; } @@ -1671,7 +2051,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, PVOID ImageBase; PIMAGE_IMPORT_BY_NAME ImportName = NULL; PIMAGE_EXPORT_DIRECTORY ExportDir; - ULONG ExportDirSize; + ULONG ExportDirSize, Length; PLIST_ENTRY Entry; /* Show debug message */ @@ -1684,20 +2064,22 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer); /* Make sure it's not too long */ - if ((Name->Length + sizeof(CHAR) + sizeof(USHORT)) > MAXLONG) + Length = Name->Length + + sizeof(CHAR) + + FIELD_OFFSET(IMAGE_IMPORT_BY_NAME, Name); + if (Length > UNICODE_STRING_MAX_BYTES) { /* Won't have enough space to add the hint */ return STATUS_NAME_TOO_LONG; } /* Check if our buffer is large enough */ - if (Name->Length >= (sizeof(ImportBuffer) - sizeof(CHAR))) + if (Name->Length > sizeof(ImportBuffer)) { /* Allocate from heap, plus 2 bytes for the Hint */ ImportName = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - Name->Length + sizeof(CHAR) + - sizeof(USHORT)); + 0, + Length); } else { @@ -1709,8 +2091,8 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, ImportName->Hint = 0; /* Copy the name and null-terminate it */ - RtlMoveMemory(ImportName->Name, Name->Buffer, Name->Length); - ImportName->Name[Name->Length] = 0; + RtlCopyMemory(ImportName->Name, Name->Buffer, Name->Length); + ImportName->Name[Name->Length] = ANSI_NULL; /* Clear the high bit */ ImageBase = ImportName; @@ -1724,16 +2106,16 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, /* Show debug message */ if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal); - if (Ordinal) - { - Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG; - } - else + /* Make sure an ordinal was given */ + if (!Ordinal) { /* No ordinal */ DPRINT1("No ordinal and no name\n"); return STATUS_INVALID_PARAMETER; } + + /* Set the orginal flag in the thunk */ + Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG; } /* Acquire lock unless we are initting */ @@ -1774,7 +2156,7 @@ LdrpGetProcedureAddress(IN PVOID BaseAddress, NULL); /* Finally, see if we're supposed to run the init routines */ - if (ExecuteInit) + if ((NT_SUCCESS(Status)) && (ExecuteInit)) { /* * It's possible a forwarded entry had us load the DLL. In that case, @@ -1842,6 +2224,7 @@ LdrpLoadDll(IN BOOLEAN Redirected, PPEB Peb = NtCurrentPeb(); NTSTATUS Status = STATUS_SUCCESS; PWCHAR p1, p2; + WCHAR c; WCHAR NameBuffer[266]; LPWSTR RawDllName; UNICODE_STRING RawDllNameString; @@ -1850,39 +2233,47 @@ LdrpLoadDll(IN BOOLEAN Redirected, /* Find the name without the extension */ p1 = DllName->Buffer; -StartLoop: p2 = NULL; while (*p1) { - if (*p1++ == L'.') + c = *p1++; + if (c == L'.') { p2 = p1; } - else if (*p1 == L'\\') + else if (c == L'\\') { - goto StartLoop; + p2 = NULL; } } /* Save the Raw DLL Name */ RawDllName = NameBuffer; - if (DllName->Length >= sizeof(NameBuffer)) - { - /* The DLL's name is too long */ - return STATUS_NAME_TOO_LONG; - } + if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG; RtlMoveMemory(RawDllName, DllName->Buffer, DllName->Length); /* Check if no extension was found or if we got a slash */ - if (!p2 || *p2 == '\\') + if (!(p2) || (*p2 == '\\')) { /* Check that we have space to add one */ - if (DllName->Length + LdrApiDefaultExtension.Length >= sizeof(NameBuffer)) + if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >= + sizeof(NameBuffer)) { /* No space to add the extension */ + DbgPrintEx(81, //DPFLTR_LDR_ID, + 0, + "LDR: %s - Dll name missing extension; with extension " + "added the name is too long\n" + " DllName: (@ %p) \"%wZ\"\n" + " DllName->Length: %u\n", + __FUNCTION__, + DllName, + DllName, + DllName->Length); return STATUS_NAME_TOO_LONG; } + /* FIXME: CLEAN THIS UP WITH Rtl String Functions */ /* Add it */ RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName + DllName->Length), LdrApiDefaultExtension.Buffer, @@ -1934,16 +2325,18 @@ StartLoop: Redirected, &LdrEntry); if (!NT_SUCCESS(Status)) goto Quickie; + + /* FIXME: Need to mark the DLL range for the stack DB */ + //RtlpStkMarkDllRange(LdrEntry); - /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */ - if (DllCharacteristics && - (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) - { - LdrEntry->EntryPoint = NULL; - LdrEntry->Flags &= ~LDRP_IMAGE_DLL; - } - - /* FIXME Mark the DLL Ranges for Stack Traces later */ + /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */ + if ((DllCharacteristics) && + (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) + { + /* This is not a DLL, so remove such data */ + LdrEntry->EntryPoint = NULL; + LdrEntry->Flags &= ~LDRP_IMAGE_DLL; + } /* Make sure it's a DLL */ if (LdrEntry->Flags & LDRP_IMAGE_DLL) @@ -1956,7 +2349,7 @@ StartLoop: } /* Update load count, unless it's locked */ - if (LdrEntry->LoadCount != -1) LdrEntry->LoadCount++; + if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++; LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT); /* Check if we failed */ @@ -1967,15 +2360,24 @@ StartLoop: InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, &LdrEntry->InInitializationOrderModuleList); - /* Cancel the load and unload the DLL */ + /* Cancel the load */ LdrpClearLoadInProgress(); + + /* Unload the DLL */ + if (ShowSnaps) + { + DbgPrint("LDR: Unloading %wZ due to error %x walking " + "import descriptors", + DllName, + Status); + } LdrUnloadDll(LdrEntry->DllBase); /* Return the error */ goto Quickie; } } - else if (LdrEntry->LoadCount != -1) + else if (LdrEntry->LoadCount != 0xFFFF) { /* Increase load count */ LdrEntry->LoadCount++; @@ -1989,12 +2391,26 @@ StartLoop: if (CallInit && LdrpLdrDatabaseIsSetup) { /* FIXME: Notify Shim Engine */ - + if (g_ShimsEnabled) + { + /* Call it */ + //ShimLoadCallback = RtlDecodeSystemPointer(g_pfnSE_DllLoaded); + //ShimLoadCallback(LdrEntry); + } + /* Run the init routine */ Status = LdrpRunInitializeRoutines(NULL); if (!NT_SUCCESS(Status)) { /* Failed, unload the DLL */ + if (ShowSnaps) + { + DbgPrint("LDR: Unloading %wZ because either its init " + "routine or one of its static imports failed; " + "status = 0x%08lx\n", + DllName, + Status); + } LdrUnloadDll(LdrEntry->DllBase); } } @@ -2007,7 +2423,7 @@ StartLoop: else { /* We were already loaded. Are we a DLL? */ - if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != -1)) + if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF)) { /* Increase load count */ LdrEntry->LoadCount++; @@ -2019,7 +2435,7 @@ StartLoop: else { /* Not a DLL, just increase the load count */ - if (LdrEntry->LoadCount != -1) LdrEntry->LoadCount++; + if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++; } } @@ -2043,407 +2459,41 @@ Quickie: return Status; } -/* - * @implemented - */ -NTSTATUS -NTAPI -LdrUnloadDll(IN PVOID BaseAddress) -{ - NTSTATUS Status = STATUS_SUCCESS; - PPEB Peb = NtCurrentPeb(); - PLDR_DATA_TABLE_ENTRY LdrEntry, CurrentEntry; - PVOID EntryPoint; - PLIST_ENTRY NextEntry; - LIST_ENTRY UnloadList; - RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; - PVOID CorImageData; - ULONG ComSectionSize; - - /* Get the LDR Lock */ - if (!LdrpInLdrInit) RtlEnterCriticalSection(Peb->LoaderLock); - - /* Increase the unload count */ - LdrpActiveUnloadCount++; - - /* Skip unload */ - if (LdrpShutdownInProgress) goto Quickie; - - /* Make sure the DLL is valid and get its entry */ - if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry)) - { - Status = STATUS_DLL_NOT_FOUND; - goto Quickie; - } - - /* Check the current Load Count */ - if (LdrEntry->LoadCount != -1) - { - /* Decrease it */ - LdrEntry->LoadCount--; - - /* If it's a dll */ - if (LdrEntry->Flags & LDRP_IMAGE_DLL) - { - /* Set up the Act Ctx */ - ActCtx.Size = sizeof(ActCtx); - ActCtx.Format = 1; - RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); - - /* Activate the ActCtx */ - RtlActivateActivationContextUnsafeFast(&ActCtx, - LdrEntry->EntryPointActivationContext); - - /* Update the load count */ - LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_DEREFCOUNT); - - /* Release the context */ - RtlDeactivateActivationContextUnsafeFast(&ActCtx); - } - } - else - { - /* The DLL is locked */ - goto Quickie; - } - - /* Show debug message */ - if (ShowSnaps) DPRINT1("LDR: UNINIT LIST\n"); - - /* Check if this is our only unload */ - if (LdrpActiveUnloadCount == 1) - { - /* Initialize the unload list */ - InitializeListHead(&LdrpUnloadHead); - } - - /* Loop the modules to build the list */ - NextEntry = Peb->Ldr->InInitializationOrderModuleList.Blink; - while (NextEntry != &Peb->Ldr->InInitializationOrderModuleList) - { - /* Get the entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); - NextEntry = NextEntry->Blink; - - /* Remove flag */ - LdrEntry->Flags &= ~LDRP_UNLOAD_IN_PROGRESS; - - /* If the load count is now 0 */ - if (!LdrEntry->LoadCount) - { - /* Show message */ - if (ShowSnaps) - { - DPRINT1("(%d) [%ws] %ws (%lx) deinit %lx\n", - LdrpActiveUnloadCount, - LdrEntry->BaseDllName.Buffer, - LdrEntry->FullDllName.Buffer, - (ULONG)LdrEntry->LoadCount, - LdrEntry->EntryPoint); - } - - /* FIXME: Call Shim Engine and notify */ - - /* Unlink it */ - CurrentEntry = LdrEntry; - RemoveEntryList(&CurrentEntry->InInitializationOrderModuleList); - RemoveEntryList(&CurrentEntry->InMemoryOrderModuleList); - RemoveEntryList(&CurrentEntry->HashLinks); - - /* If there's more then one active unload */ - if (LdrpActiveUnloadCount > 1) - { - /* Flush the cached DLL handle and clear the list */ - LdrpLoadedDllHandleCache = NULL; - CurrentEntry->InMemoryOrderModuleList.Flink = NULL; - } - - /* Add the entry on the unload list */ - InsertTailList(&LdrpUnloadHead, &CurrentEntry->HashLinks); - } - } - - /* Only call the entrypoints once */ - if (LdrpActiveUnloadCount > 1) goto Quickie; - - /* Now loop the unload list and create our own */ - InitializeListHead(&UnloadList); - CurrentEntry = NULL; - NextEntry = LdrpUnloadHead.Flink; - while (NextEntry != &LdrpUnloadHead) - { - /* If we have an active entry */ - if (CurrentEntry) - { - /* Remove it */ - RemoveEntryList(&CurrentEntry->InLoadOrderLinks); - CurrentEntry = NULL; - - /* Reset list pointers */ - NextEntry = LdrpUnloadHead.Flink; - if (NextEntry == &LdrpUnloadHead) break; - } - - /* Get the current entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks); - - /* Log the Unload Event */ - //LdrpRecordUnloadEvent(LdrEntry); - - /* Set the entry and clear it from the list */ - CurrentEntry = LdrEntry; - LdrpLoadedDllHandleCache = NULL; - CurrentEntry->InMemoryOrderModuleList.Flink = NULL; - - /* Move it from the global to the local list */ - RemoveEntryList(&CurrentEntry->HashLinks); - InsertTailList(&UnloadList, &CurrentEntry->HashLinks); - - /* Get the entrypoint */ - EntryPoint = LdrEntry->EntryPoint; - - /* Check if we should call it */ - if (EntryPoint && (LdrEntry->Flags & LDRP_PROCESS_ATTACH_CALLED)) - { - /* Show message */ - if (ShowSnaps) - { - DPRINT1("LDR: Calling deinit %lx\n", EntryPoint); - } - - /* Set up the Act Ctx */ - ActCtx.Size = sizeof(ActCtx); - ActCtx.Format = 1; - RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); - - /* Activate the ActCtx */ - RtlActivateActivationContextUnsafeFast(&ActCtx, - LdrEntry->EntryPointActivationContext); - - /* Call the entrypoint */ - LdrpCallDllEntry(LdrEntry->EntryPoint, - LdrEntry->DllBase, - DLL_PROCESS_DETACH, - NULL); - - /* Release the context */ - RtlDeactivateActivationContextUnsafeFast(&ActCtx); - } - - /* Remove it from the list */ - RemoveEntryList(&CurrentEntry->InLoadOrderLinks); - CurrentEntry = NULL; - NextEntry = LdrpUnloadHead.Flink; - } - - /* Now loop our local list */ - NextEntry = UnloadList.Flink; - while (NextEntry != &UnloadList) - { - /* Get the entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, HashLinks); - NextEntry = NextEntry->Flink; - CurrentEntry = LdrEntry; - - /* Notify Application Verifier */ - if (Peb->NtGlobalFlag & FLG_HEAP_ENABLE_TAIL_CHECK) - { - DPRINT1("We don't support Application Verifier yet\n"); - } - - /* Show message */ - if (ShowSnaps) - { - DPRINT1("LDR: Unmapping [%ws]\n", LdrEntry->BaseDllName.Buffer); - } - - /* Check if this is a .NET executable */ - if ((CorImageData = RtlImageDirectoryEntryToData(LdrEntry->DllBase, - TRUE, - IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, - &ComSectionSize))) - { - /* FIXME */ - DPRINT1(".NET Images are not supported yet\n"); - } - - /* Check if we should unmap*/ - if (!(CurrentEntry->Flags & LDR_COR_OWNS_UNMAP)) - { - /* Unmap the DLL */ - Status = NtUnmapViewOfSection(NtCurrentProcess(), - CurrentEntry->DllBase); - } - - /* Unload the alternate resource module, if any */ - LdrUnloadAlternateResourceModule(CurrentEntry->DllBase); - - /* Send shutdown notification */ - //LdrpSendDllNotifications(CurrentEntry, 2, LdrpShutdownInProgress); - - /* Check if a Hotpatch is active */ - if (LdrEntry->PatchInformation) - { - /* FIXME */ - DPRINT1("We don't support Hotpatching yet\n"); - } - - /* Deallocate the Entry */ - LdrpFinalizeAndDeallocateDataTableEntry(CurrentEntry); - - /* If this is the cached entry, invalide it */ - if (LdrpGetModuleHandleCache == CurrentEntry) - { - LdrpGetModuleHandleCache = NULL; - } - } - -Quickie: - /* Decrease unload count */ - LdrpActiveUnloadCount--; - if (!LdrpInLdrInit) RtlLeaveCriticalSection(Peb->LoaderLock); - - /* FIXME: Rundown the Hotpatch data, if present */ - - /* Return to caller */ - return Status; -} - ULONG NTAPI -LdrpClearLoadInProgress() +LdrpClearLoadInProgress(VOID) { - PLIST_ENTRY ListHead; - PLIST_ENTRY Entry; - PLDR_DATA_TABLE_ENTRY Module; + PLIST_ENTRY ListHead, Entry; + PLDR_DATA_TABLE_ENTRY LdrEntry; ULONG ModulesCount = 0; /* Traverse the init list */ ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList; Entry = ListHead->Flink; - while (Entry != ListHead) { - Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList); + /* Get the loader entry */ + LdrEntry = CONTAINING_RECORD(Entry, + LDR_DATA_TABLE_ENTRY, + InInitializationOrderModuleList); /* Clear load in progress flag */ - Module->Flags &= ~LDRP_LOAD_IN_PROGRESS; + LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS; - /* Increase counter for modules with entry point count but not processed yet */ - if (Module->EntryPoint && - !(Module->Flags & LDRP_ENTRY_PROCESSED)) ModulesCount++; + /* Check for modules with entry point count but not processed yet */ + if ((LdrEntry->EntryPoint) && + !(LdrEntry->Flags & LDRP_ENTRY_PROCESSED)) + { + /* Increase counter */ + ModulesCount++; + } /* Advance to the next entry */ Entry = Entry->Flink; } + /* Return final count */ return ModulesCount; } -/* - * @implemented - */ -NTSTATUS NTAPI -LdrAddRefDll(IN ULONG Flags, - IN PVOID BaseAddress) -{ - PLDR_DATA_TABLE_ENTRY LdrEntry; - NTSTATUS Status = STATUS_SUCCESS; - ULONG Cookie; - BOOLEAN Locked = FALSE; - - /* Check for invalid flags */ - if (Flags & ~(LDR_PIN_MODULE)) - { - /* Fail with invalid parameter status if so */ - Status = STATUS_INVALID_PARAMETER; - goto quickie; - } - - /* Acquire the loader lock if not in init phase */ - if (!LdrpInLdrInit) - { - /* Acquire the lock */ - Status = LdrLockLoaderLock(0, NULL, &Cookie); - if (!NT_SUCCESS(Status)) goto quickie; - Locked = TRUE; - } - - /* Get this module's data table entry */ - if (LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry)) - { - if (!LdrEntry) - { - /* Shouldn't happen */ - Status = STATUS_INTERNAL_ERROR; - goto quickie; - } - - /* If this is not a pinned module */ - if (LdrEntry->LoadCount != -1) - { - /* Update its load count */ - if (Flags & LDR_PIN_MODULE) - { - /* Pin it by setting load count to -1 */ - LdrEntry->LoadCount = -1; - LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_PIN); - } - else - { - /* Increase its load count by one */ - LdrEntry->LoadCount++; - LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT); - } - - /* Clear load in progress */ - LdrpClearLoadInProgress(); - } - } - else - { - /* There was an error getting this module's handle, return invalid param status */ - Status = STATUS_INVALID_PARAMETER; - goto quickie; - } - -quickie: - if (!NT_SUCCESS(Status)) - { - if (ShowSnaps || - (Status != STATUS_NO_SUCH_FILE && - Status != STATUS_DLL_NOT_FOUND && - Status != STATUS_OBJECT_NAME_NOT_FOUND)) - { - DPRINT1("LDR: LdrAddRefDll(%p) 0x%08lx\n", BaseAddress); - } - } - - /* Release the lock if needed */ - if (Locked) LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); - - return Status; -} - - -BOOLEAN -NTAPI -LdrpFreeUnicodeString(PUNICODE_STRING String) -{ - BOOLEAN Result = FALSE; - - ASSERT(String != NULL); - - /* If Buffer is not NULL - free it */ - if (String->Buffer) - Result = RtlFreeHeap(RtlGetProcessHeap(), 0, String->Buffer); - - /* Zero it out */ - String->Length = 0; - String->MaximumLength = 0; - String->Buffer = NULL; - - return Result; -} - /* EOF */ diff --git a/dll/ntdll/ldr/startup.c b/dll/ntdll/ldr/startup.c deleted file mode 100644 index 90c2ca8b417..00000000000 --- a/dll/ntdll/ldr/startup.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: dll/ntdll/ldr/startup.c - * PURPOSE: Process startup for PE executables - * PROGRAMMERS: Jean Michault - * Rex Jolliff (rex@lvcablemodem.com) - */ - -/* INCLUDES *****************************************************************/ - -#include -//#define NDEBUG -#include -#include - -VOID RtlInitializeHeapManager(VOID); -extern PTEB LdrpTopLevelDllBeingLoadedTeb; -VOID NTAPI RtlpInitDeferedCriticalSection(VOID); -VOID RtlpInitializeVectoredExceptionHandling(VOID); - -/* GLOBALS *******************************************************************/ - -extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry; -extern RTL_CRITICAL_SECTION FastPebLock; -extern RTL_BITMAP TlsBitMap; -extern RTL_BITMAP TlsExpansionBitMap; - -#define VALUE_BUFFER_SIZE 256 - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -FASTCALL -ReadCompatibilitySetting(HANDLE Key, - LPWSTR Value, - PKEY_VALUE_PARTIAL_INFORMATION ValueInfo, - DWORD * Buffer) -{ - UNICODE_STRING ValueName; - NTSTATUS Status; - ULONG Length; - - RtlInitUnicodeString(&ValueName, Value); - Status = NtQueryValueKey(Key, - &ValueName, - KeyValuePartialInformation, - ValueInfo, - VALUE_BUFFER_SIZE, - &Length); - - if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_DWORD)) - { - RtlFreeUnicodeString(&ValueName); - return FALSE; - } - - RtlCopyMemory(Buffer, &ValueInfo->Data[0], sizeof(DWORD)); - RtlFreeUnicodeString(&ValueName); - return TRUE; -} - -VOID -FASTCALL -LoadImageFileExecutionOptions(PPEB Peb) -{ - NTSTATUS Status = STATUS_SUCCESS; - ULONG Value = 0; - UNICODE_STRING ImageName; - UNICODE_STRING ImagePathName; - ULONG ValueSize; - extern ULONG RtlpDphGlobalFlags, RtlpPageHeapSizeRangeStart, RtlpPageHeapSizeRangeEnd; - extern ULONG RtlpPageHeapDllRangeStart, RtlpPageHeapDllRangeEnd; - extern WCHAR RtlpDphTargetDlls[512]; - extern BOOLEAN RtlpPageHeapEnabled; - - if (Peb->ProcessParameters && - Peb->ProcessParameters->ImagePathName.Length > 0) - { - DPRINT("%wZ\n", &Peb->ProcessParameters->ImagePathName); - - ImagePathName = Peb->ProcessParameters->ImagePathName; - ImageName.Buffer = ImagePathName.Buffer + ImagePathName.Length / sizeof(WCHAR); - ImageName.Length = 0; - - while (ImagePathName.Buffer < ImageName.Buffer) - { - ImageName.Buffer--; - if (*ImageName.Buffer == L'\\') - { - ImageName.Buffer++; - break; - } - } - - ImageName.Length = ImagePathName.Length - - (ImageName.Buffer - ImagePathName.Buffer) * sizeof(WCHAR); - ImageName.MaximumLength = ImageName.Length + - ImagePathName.MaximumLength - ImagePathName.Length; - - DPRINT("%wZ\n", &ImageName); - - /* global flag */ - Status = LdrQueryImageFileExecutionOptions(&ImageName, - L"GlobalFlag", - REG_DWORD, - (PVOID)&Value, - sizeof(Value), - &ValueSize); - if (NT_SUCCESS(Status)) - { - Peb->NtGlobalFlag = Value; - DPRINT("GlobalFlag: Value=0x%lx\n", Value); - } - else - { - /* Add debugging flags if there is no GlobalFlags override */ - if (Peb->BeingDebugged) - { - Peb->NtGlobalFlag |= FLG_HEAP_VALIDATE_PARAMETERS | - FLG_HEAP_ENABLE_FREE_CHECK | - FLG_HEAP_ENABLE_TAIL_CHECK; - } - } - - /* Handle the case when page heap is enabled */ - if (Peb->NtGlobalFlag & FLG_HEAP_PAGE_ALLOCS) - { - /* Disable all heap debugging flags so that no heap call goes via page heap branch */ - Peb->NtGlobalFlag &= ~(FLG_HEAP_VALIDATE_PARAMETERS | - FLG_HEAP_VALIDATE_ALL | - FLG_HEAP_ENABLE_FREE_CHECK | - FLG_HEAP_ENABLE_TAIL_CHECK | - FLG_USER_STACK_TRACE_DB | - FLG_HEAP_ENABLE_TAGGING | - FLG_HEAP_ENABLE_TAG_BY_DLL); - - /* Get page heap flags without checking return value */ - LdrQueryImageFileExecutionOptions(&ImageName, - L"PageHeapFlags", - REG_DWORD, - (PVOID)&RtlpDphGlobalFlags, - sizeof(RtlpDphGlobalFlags), - &ValueSize); - - LdrQueryImageFileExecutionOptions(&ImageName, - L"PageHeapSizeRangeStart", - REG_DWORD, - (PVOID)&RtlpPageHeapSizeRangeStart, - sizeof(RtlpPageHeapSizeRangeStart), - &ValueSize); - - LdrQueryImageFileExecutionOptions(&ImageName, - L"PageHeapSizeRangeEnd", - REG_DWORD, - (PVOID)&RtlpPageHeapSizeRangeEnd, - sizeof(RtlpPageHeapSizeRangeEnd), - &ValueSize); - - LdrQueryImageFileExecutionOptions(&ImageName, - L"PageHeapDllRangeStart", - REG_DWORD, - (PVOID)&RtlpPageHeapDllRangeStart, - sizeof(RtlpPageHeapDllRangeStart), - &ValueSize); - - LdrQueryImageFileExecutionOptions(&ImageName, - L"PageHeapDllRangeEnd", - REG_DWORD, - (PVOID)&RtlpPageHeapDllRangeEnd, - sizeof(RtlpPageHeapDllRangeEnd), - &ValueSize); - - LdrQueryImageFileExecutionOptions(&ImageName, - L"PageHeapTargetDlls", - REG_SZ, - (PVOID)RtlpDphTargetDlls, - sizeof(RtlpDphTargetDlls), - &ValueSize); - - /* Now when all parameters are read, enable page heap */ - RtlpPageHeapEnabled = TRUE; - } - } -} - -BOOLEAN -FASTCALL -LoadCompatibilitySettings(PPEB Peb) -{ - NTSTATUS Status; - HANDLE UserKey = NULL; - HANDLE KeyHandle; - HANDLE SubKeyHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyName = RTL_CONSTANT_STRING( - L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"); - UNICODE_STRING ValueName; - UCHAR ValueBuffer[VALUE_BUFFER_SIZE]; - PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; - ULONG Length; - DWORD MajorVersion, MinorVersion, BuildNumber, PlatformId, - SPMajorVersion, SPMinorVersion = 0; - - if (Peb->ProcessParameters && - (Peb->ProcessParameters->ImagePathName.Length > 0)) - { - Status = RtlOpenCurrentUser(KEY_READ, &UserKey); - if (!NT_SUCCESS(Status)) - { - return FALSE; - } - - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - UserKey, - NULL); - - Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - if (UserKey) - NtClose(UserKey); - return FALSE; - } - - /* query version name for application */ - ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ValueBuffer; - Status = NtQueryValueKey(KeyHandle, - &Peb->ProcessParameters->ImagePathName, - KeyValuePartialInformation, - ValueBuffer, - VALUE_BUFFER_SIZE, - &Length); - - if (!NT_SUCCESS(Status) || (ValueInfo->Type != REG_SZ)) - { - NtClose(KeyHandle); - if (UserKey) - NtClose(UserKey); - return FALSE; - } - - ValueName.Length = ValueInfo->DataLength; - ValueName.MaximumLength = ValueInfo->DataLength; - ValueName.Buffer = (PWSTR) ValueInfo->Data; - - /* load version info */ - InitializeObjectAttributes(&ObjectAttributes, - &ValueName, - OBJ_CASE_INSENSITIVE, - KeyHandle, - NULL); - - Status = NtOpenKey(&SubKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - NtClose(KeyHandle); - if (UserKey) - NtClose(UserKey); - return FALSE; - } - - DPRINT("Loading version information for: %wZ\n", &ValueName); - - /* read settings from registry */ - if (!ReadCompatibilitySetting(SubKeyHandle, L"MajorVersion", ValueInfo, &MajorVersion)) - goto finish; - if (!ReadCompatibilitySetting(SubKeyHandle, L"MinorVersion", ValueInfo, &MinorVersion)) - goto finish; - if (!ReadCompatibilitySetting(SubKeyHandle, L"BuildNumber", ValueInfo, &BuildNumber)) - goto finish; - if (!ReadCompatibilitySetting(SubKeyHandle, L"PlatformId", ValueInfo, &PlatformId)) - goto finish; - - /* now assign the settings */ - Peb->OSMajorVersion = (ULONG) MajorVersion; - Peb->OSMinorVersion = (ULONG) MinorVersion; - Peb->OSBuildNumber = (USHORT) BuildNumber; - Peb->OSPlatformId = (ULONG) PlatformId; - - /* optional service pack version numbers */ - if (ReadCompatibilitySetting(SubKeyHandle, - L"SPMajorVersion", - ValueInfo, - &SPMajorVersion) && - ReadCompatibilitySetting(SubKeyHandle, - L"SPMinorVersion", - ValueInfo, - &SPMinorVersion)) - { - Peb->OSCSDVersion = ((SPMajorVersion & 0xFF) << 8) | - (SPMinorVersion & 0xFF); - } - -finish: - /* we're finished */ - NtClose(SubKeyHandle); - NtClose(KeyHandle); - if (UserKey) - NtClose(UserKey); - return TRUE; - } - - return FALSE; -} - -/* EOF */ diff --git a/dll/ntdll/ldr/utils.c b/dll/ntdll/ldr/utils.c deleted file mode 100644 index fe39e90053d..00000000000 --- a/dll/ntdll/ldr/utils.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: lib/ntdll/ldr/utils.c - * PURPOSE: Process startup for PE executables - * PROGRAMMERS: Jean Michault - * Rex Jolliff (rex@lvcablemodem.com) - * Michael Martin - */ - -/* - * TODO: - * - Handle loading flags correctly - * - Handle errors correctly (unload dll's) - * - Implement a faster way to find modules (hash table) - * - any more ?? - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -#define LDRP_PROCESS_CREATION_TIME 0xffff -#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m))) - -/* GLOBALS *******************************************************************/ - -#ifdef NDEBUG -#define TRACE_LDR(...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); } -#endif - -static BOOLEAN LdrpDllShutdownInProgress = FALSE; -extern HANDLE LdrpKnownDllObjectDirectory; -extern UNICODE_STRING LdrpKnownDllPath; -static PLDR_DATA_TABLE_ENTRY LdrpLastModule = NULL; -extern PLDR_DATA_TABLE_ENTRY LdrpImageEntry; - -/* PROTOTYPES ****************************************************************/ - -static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_DATA_TABLE_ENTRY *Module, BOOLEAN Ref); -static PVOID LdrFixupForward(PCHAR ForwardName); -static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint); - -NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fulldosname ); -NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module ); - -/* FUNCTIONS *****************************************************************/ - -static __inline LONG LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Locked) -{ - LONG LoadCount; - if (!Locked) - { - RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); - } - LoadCount = Module->LoadCount; - if (Module->LoadCount > 0 && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) - { - Module->LoadCount--; - } - if (!Locked) - { - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - } - return LoadCount; -} - -static __inline LONG LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEAN Locked) -{ - LONG LoadCount; - if (!Locked) - { - RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); - } - LoadCount = Module->LoadCount; - if (Module->LoadCount != LDRP_PROCESS_CREATION_TIME) - { - Module->LoadCount++; - } - if (!Locked) - { - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - } - return LoadCount; -} - -/*************************************************************************** - * NAME LOCAL - * LdrAdjustDllName - * - * DESCRIPTION - * Adjusts the name of a dll to a fully qualified name. - * - * ARGUMENTS - * FullDllName: Pointer to caller supplied storage for the fully - * qualified dll name. - * DllName: Pointer to the dll name. - * BaseName: TRUE: Only the file name is passed to FullDllName - * FALSE: The full path is preserved in FullDllName - * - * RETURN VALUE - * None - * - * REVISIONS - * - * NOTE - * A given path is not affected by the adjustment, but the file - * name only: - * ntdll --> ntdll.dll - * ntdll. --> ntdll - * ntdll.xyz --> ntdll.xyz - */ -static VOID -LdrAdjustDllName (PUNICODE_STRING FullDllName, - PUNICODE_STRING DllName, - BOOLEAN BaseName) -{ - WCHAR Buffer[MAX_PATH]; - ULONG Length; - PWCHAR Extension; - PWCHAR Pointer; - - DPRINT1("\n"); - - Length = DllName->Length / sizeof(WCHAR); - - if (BaseName) - { - /* get the base dll name */ - Pointer = DllName->Buffer + Length; - Extension = Pointer; - - do - { - --Pointer; - } - while (Pointer >= DllName->Buffer && *Pointer != L'\\' && *Pointer != L'/'); - - Pointer++; - Length = Extension - Pointer; - memmove (Buffer, Pointer, Length * sizeof(WCHAR)); - Buffer[Length] = L'\0'; - } - else - { - /* get the full dll name */ - memmove (Buffer, DllName->Buffer, DllName->Length); - Buffer[DllName->Length / sizeof(WCHAR)] = L'\0'; - } - - /* Build the DLL's absolute name */ - Extension = wcsrchr (Buffer, L'.'); - if ((Extension != NULL) && (*Extension == L'.')) - { - /* with extension - remove dot if it's the last character */ - if (Buffer[Length - 1] == L'.') - Length--; - Buffer[Length] = 0; - } - else - { - /* name without extension - assume that it is .dll */ - memmove (Buffer + Length, L".dll", 10); - } - - RtlCreateUnicodeString(FullDllName, Buffer); -} - -PLDR_DATA_TABLE_ENTRY -LdrAddModuleEntry(PVOID ImageBase, - PIMAGE_NT_HEADERS NTHeaders, - PWSTR FullDosName) -{ - PLDR_DATA_TABLE_ENTRY Module; - - DPRINT1("\n"); - - Module = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY)); - ASSERT(Module); - memset(Module, 0, sizeof(LDR_DATA_TABLE_ENTRY)); - Module->DllBase = (PVOID)ImageBase; - Module->EntryPoint = (PVOID)NTHeaders->OptionalHeader.AddressOfEntryPoint; - if (Module->EntryPoint != 0) - Module->EntryPoint = (PVOID)((ULONG_PTR)Module->EntryPoint + (ULONG_PTR)Module->DllBase); - Module->SizeOfImage = LdrpGetResidentSize(NTHeaders); - if (NtCurrentPeb()->Ldr->Initialized == TRUE) - { - /* loading while app is running */ - Module->LoadCount = 1; - } - else - { - /* - * loading while app is initializing - * dll must not be unloaded - */ - Module->LoadCount = LDRP_PROCESS_CREATION_TIME; - } - - Module->Flags = 0; - Module->TlsIndex = -1; - Module->CheckSum = NTHeaders->OptionalHeader.CheckSum; - Module->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; - - RtlCreateUnicodeString (&Module->FullDllName, - FullDosName); - RtlCreateUnicodeString (&Module->BaseDllName, - wcsrchr(FullDosName, L'\\') + 1); - DPRINT ("BaseDllName %wZ\n", &Module->BaseDllName); - - RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); - InsertTailList(&NtCurrentPeb()->Ldr->InLoadOrderModuleList, - &Module->InLoadOrderLinks); - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - - return(Module); -} - -/*************************************************************************** - * NAME LOCAL - * LdrFindEntryForName - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * - */ -static NTSTATUS -LdrFindEntryForName(PUNICODE_STRING Name, - PLDR_DATA_TABLE_ENTRY *Module, - BOOLEAN Ref) -{ - PLIST_ENTRY ModuleListHead; - PLIST_ENTRY Entry; - PLDR_DATA_TABLE_ENTRY ModulePtr; - BOOLEAN ContainsPath; - UNICODE_STRING AdjustedName; - - DPRINT("LdrFindEntryForName(Name %wZ)\n", Name); - - if (NtCurrentPeb()->Ldr == NULL) - return(STATUS_NO_MORE_ENTRIES); - - RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock); - ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; - Entry = ModuleListHead->Flink; - if (Entry == ModuleListHead) - { - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - return(STATUS_NO_MORE_ENTRIES); - } - - // NULL is the current process - if (Name == NULL) - { - *Module = LdrpImageEntry; - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - return(STATUS_SUCCESS); - } - - ContainsPath = (Name->Length >= 2 * sizeof(WCHAR) && L':' == Name->Buffer[1]); - LdrAdjustDllName (&AdjustedName, Name, !ContainsPath); - - if (LdrpLastModule) - { - if ((!ContainsPath && - 0 == RtlCompareUnicodeString(&LdrpLastModule->BaseDllName, &AdjustedName, TRUE)) || - (ContainsPath && - 0 == RtlCompareUnicodeString(&LdrpLastModule->FullDllName, &AdjustedName, TRUE))) - { - *Module = LdrpLastModule; - if (Ref && (*Module)->LoadCount != LDRP_PROCESS_CREATION_TIME) - { - (*Module)->LoadCount++; - } - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - RtlFreeUnicodeString(&AdjustedName); - return(STATUS_SUCCESS); - } - } - while (Entry != ModuleListHead) - { - ModulePtr = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - DPRINT("Scanning %wZ %wZ\n", &ModulePtr->BaseDllName, &AdjustedName); - - if ((!ContainsPath && - 0 == RtlCompareUnicodeString(&ModulePtr->BaseDllName, &AdjustedName, TRUE)) || - (ContainsPath && - 0 == RtlCompareUnicodeString(&ModulePtr->FullDllName, &AdjustedName, TRUE))) - { - *Module = LdrpLastModule = ModulePtr; - if (Ref && ModulePtr->LoadCount != LDRP_PROCESS_CREATION_TIME) - { - ModulePtr->LoadCount++; - } - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - RtlFreeUnicodeString(&AdjustedName); - return(STATUS_SUCCESS); - } - - Entry = Entry->Flink; - } - - DPRINT("Failed to find dll %wZ\n", Name); - RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); - RtlFreeUnicodeString(&AdjustedName); - return(STATUS_NO_MORE_ENTRIES); -} - -/********************************************************************** - * NAME LOCAL - * LdrFixupForward - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * - */ -static PVOID -LdrFixupForward(PCHAR ForwardName) -{ - CHAR NameBuffer[128]; - UNICODE_STRING DllName; - NTSTATUS Status; - PCHAR p; - PLDR_DATA_TABLE_ENTRY Module; - PVOID BaseAddress; - - DPRINT1("\n"); - - strcpy(NameBuffer, ForwardName); - p = strchr(NameBuffer, '.'); - if (p != NULL) - { - *p = 0; - - DPRINT("Dll: %s Function: %s\n", NameBuffer, p+1); - RtlCreateUnicodeStringFromAsciiz (&DllName, - NameBuffer); - - Status = LdrFindEntryForName (&DllName, &Module, FALSE); - /* FIXME: - * The caller (or the image) is responsible for loading of the dll, where the function is forwarded. - */ - if (!NT_SUCCESS(Status)) - { - Status = LdrLoadDll(NULL, NULL, &DllName, &BaseAddress); - if (NT_SUCCESS(Status)) - { - Status = LdrFindEntryForName (&DllName, &Module, FALSE); - } - } - RtlFreeUnicodeString (&DllName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer); - return NULL; - } - - DPRINT("BaseAddress: %p\n", Module->DllBase); - - return LdrGetExportByName(Module->DllBase, (PUCHAR)(p+1), -1); - } - - return NULL; -} - - -/********************************************************************** - * NAME LOCAL - * LdrGetExportByName - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * AddressOfNames and AddressOfNameOrdinals are paralell tables, - * both with NumberOfNames entries. - * - */ -static PVOID -LdrGetExportByName(PVOID BaseAddress, - PUCHAR SymbolName, - WORD Hint) -{ - PIMAGE_EXPORT_DIRECTORY ExportDir; - PDWORD *ExFunctions; - PDWORD *ExNames; - USHORT *ExOrdinals; - PVOID ExName; - ULONG Ordinal; - PVOID Function; - LONG minn, maxn; - ULONG ExportDirSize; - - DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress, SymbolName, Hint); - - ExportDir = (PIMAGE_EXPORT_DIRECTORY) - RtlImageDirectoryEntryToData(BaseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportDirSize); - if (ExportDir == NULL) - { - DPRINT1("LdrGetExportByName(): no export directory, " - "can't lookup %s/%hu!\n", SymbolName, Hint); - return NULL; - } - - - //The symbol names may be missing entirely - if (ExportDir->AddressOfNames == 0) - { - DPRINT("LdrGetExportByName(): symbol names missing entirely\n"); - return NULL; - } - - /* - * Get header pointers - */ - ExNames = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfNames); - ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); - ExFunctions = (PDWORD *)RVA(BaseAddress, ExportDir->AddressOfFunctions); - - /* - * Check the hint first - */ - if (Hint < ExportDir->NumberOfNames) - { - ExName = RVA(BaseAddress, ExNames[Hint]); - if (strcmp(ExName, (PCHAR)SymbolName) == 0) - { - Ordinal = ExOrdinals[Hint]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - if (((ULONG)Function >= (ULONG)ExportDir) && - ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize)) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrFixupForward((PCHAR)Function); - if (Function == NULL) - { - DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName); - } - return Function; - } - if (Function != NULL) - return Function; - } - } - - /* - * Binary search - */ - minn = 0; - maxn = ExportDir->NumberOfNames - 1; - while (minn <= maxn) - { - LONG mid; - LONG res; - - mid = (minn + maxn) / 2; - - ExName = RVA(BaseAddress, ExNames[mid]); - res = strcmp(ExName, (PCHAR)SymbolName); - if (res == 0) - { - Ordinal = ExOrdinals[mid]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - if (((ULONG)Function >= (ULONG)ExportDir) && - ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize)) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrFixupForward((PCHAR)Function); - if (Function == NULL) - { - DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName); - } - return Function; - } - if (Function != NULL) - return Function; - } - else if (minn == maxn) - { - DPRINT("LdrGetExportByName(): binary search failed\n"); - break; - } - else if (res > 0) - { - maxn = mid - 1; - } - else - { - minn = mid + 1; - } - } - - DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName); - return (PVOID)NULL; -} - - -/********************************************************************** - * NAME LOCAL - * LdrPerformRelocations - * - * DESCRIPTION - * Relocate a DLL's memory image. - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - * - * NOTE - * - */ -NTSTATUS -LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders, - PVOID ImageBase) -{ - PIMAGE_DATA_DIRECTORY RelocationDDir; - PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; - ULONG Count, ProtectSize, OldProtect, OldProtect2; - PVOID Page, ProtectPage, ProtectPage2; - PUSHORT TypeOffset; - LONG_PTR Delta; - NTSTATUS Status; - - DPRINT1("\n"); - - if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) - { - return STATUS_SUCCESS; - } - - RelocationDDir = - &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; - - if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0) - { - return STATUS_SUCCESS; - } - - ProtectSize = PAGE_SIZE; - Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase; - RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase + - RelocationDDir->VirtualAddress); - RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase + - RelocationDDir->VirtualAddress + RelocationDDir->Size); - - while (RelocationDir < RelocationEnd && - RelocationDir->SizeOfBlock > 0) - { - Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / - sizeof(USHORT); - Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress); - TypeOffset = (PUSHORT)(RelocationDir + 1); - - /* Unprotect the page(s) we're about to relocate. */ - ProtectPage = Page; - Status = NtProtectVirtualMemory(NtCurrentProcess(), - &ProtectPage, - &ProtectSize, - PAGE_READWRITE, - &OldProtect); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to unprotect relocation target.\n"); - return Status; - } - - if (RelocationDir->VirtualAddress + PAGE_SIZE < - NTHeaders->OptionalHeader.SizeOfImage) - { - ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE); - Status = NtProtectVirtualMemory(NtCurrentProcess(), - &ProtectPage2, - &ProtectSize, - PAGE_READWRITE, - &OldProtect2); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to unprotect relocation target (2).\n"); - NtProtectVirtualMemory(NtCurrentProcess(), - &ProtectPage, - &ProtectSize, - OldProtect, - &OldProtect); - return Status; - } - } - else - { - ProtectPage2 = NULL; - } - - RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page, - Count, - TypeOffset, - Delta); - if (RelocationDir == NULL) - return STATUS_UNSUCCESSFUL; - - /* Restore old page protection. */ - NtProtectVirtualMemory(NtCurrentProcess(), - &ProtectPage, - &ProtectSize, - OldProtect, - &OldProtect); - - if (ProtectPage2 != NULL) - { - NtProtectVirtualMemory(NtCurrentProcess(), - &ProtectPage2, - &ProtectSize, - OldProtect2, - &OldProtect2); - } - } - - return STATUS_SUCCESS; -} - -void -RtlpRaiseImportNotFound(CHAR *FuncName, ULONG Ordinal, PUNICODE_STRING DllName) -{ - ULONG ErrorResponse; - ULONG_PTR ErrorParameters[2]; - ANSI_STRING ProcNameAnsi; - ANSI_STRING DllNameAnsi; - CHAR Buffer[8]; - - DPRINT1("\n"); - - if (!FuncName) - { - _snprintf(Buffer, 8, "# %ld", Ordinal); - FuncName = Buffer; - } - - RtlInitAnsiString(&ProcNameAnsi, FuncName); - RtlUnicodeStringToAnsiString(&DllNameAnsi, DllName, TRUE); - ErrorParameters[0] = (ULONG_PTR)&ProcNameAnsi; - ErrorParameters[1] = (ULONG_PTR)&DllNameAnsi; - NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND, - 2, - 3, - ErrorParameters, - OptionOk, - &ErrorResponse); - RtlFreeAnsiString(&DllNameAnsi); -} - -/* - * @implemented - */ -NTSTATUS NTAPI -LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress) -{ - PLIST_ENTRY ModuleListHead; - PLIST_ENTRY Entry; - PLDR_DATA_TABLE_ENTRY Module; - NTSTATUS Status; - - DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress); - - Status = STATUS_DLL_NOT_FOUND; - RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); - ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; - Entry = ModuleListHead->Flink; - while (Entry != ModuleListHead) - { - Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module->BaseDllName, Module->DllBase); - - if (Module->DllBase == BaseAddress) - { - if (Module->TlsIndex == 0xFFFF) - { - Module->Flags |= LDRP_DONT_CALL_FOR_THREADS; - Status = STATUS_SUCCESS; - } - break; - } - Entry = Entry->Flink; - } - RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); - return Status; -} - -/* - * @implemented - */ -BOOLEAN NTAPI -RtlDllShutdownInProgress (VOID) -{ - DPRINT1("\n"); - return LdrpDllShutdownInProgress; -} - -/* - * Compute size of an image as it is actually present in virt memory - * (i.e. excluding NEVER_LOAD sections) - */ -ULONG -LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders) -{ - PIMAGE_SECTION_HEADER SectionHeader; - unsigned SectionIndex; - ULONG ResidentSize; - - DPRINT1("\n"); - - SectionHeader = (PIMAGE_SECTION_HEADER)((char *) &NTHeaders->OptionalHeader - + NTHeaders->FileHeader.SizeOfOptionalHeader); - ResidentSize = 0; - for (SectionIndex = 0; - SectionIndex < NTHeaders->FileHeader.NumberOfSections; - SectionIndex++) - { - if (0 == (SectionHeader->Characteristics & IMAGE_SCN_LNK_REMOVE) - && ResidentSize < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) - { - ResidentSize = SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize; - } - SectionHeader++; - } - - return ResidentSize; -} - -PIMAGE_BASE_RELOCATION -NTAPI -LdrProcessRelocationBlock( - IN ULONG_PTR Address, - IN ULONG Count, - IN PUSHORT TypeOffset, - IN LONG_PTR Delta) -{ - DPRINT1("\n"); - return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta); -} - -BOOLEAN -NTAPI -LdrUnloadAlternateResourceModule(IN PVOID BaseAddress) -{ - //FIXME: We don't implement alternate resources anyway, don't spam the log - //UNIMPLEMENTED; - return FALSE; -} diff --git a/dll/shellext/fontext/CMakeLists.txt b/dll/shellext/fontext/CMakeLists.txt index cd57d0ed73e..b4d7e43dae8 100644 --- a/dll/shellext/fontext/CMakeLists.txt +++ b/dll/shellext/fontext/CMakeLists.txt @@ -25,4 +25,5 @@ add_importlibs(fontext kernel32 ntdll) +add_pch(fontext fontext.h) add_cd_file(TARGET fontext DESTINATION reactos/system32 FOR all) diff --git a/dll/shellext/fontext/fontext.h b/dll/shellext/fontext/fontext.h index c62ce1c49a0..aa965a6125e 100644 --- a/dll/shellext/fontext/fontext.h +++ b/dll/shellext/fontext/fontext.h @@ -1,9 +1,7 @@ -#pragma once - #define COBJMACROS #include #include #include #include - +#include #include diff --git a/dll/shellext/fontext/regsvr.c b/dll/shellext/fontext/regsvr.c index b3f21df297e..5cc6344bff3 100644 --- a/dll/shellext/fontext/regsvr.c +++ b/dll/shellext/fontext/regsvr.c @@ -8,10 +8,7 @@ * 10-06-2008 Created */ -#include -#include - -#include +#include "fontext.h" static HRESULT REGSVR_RegisterServer() diff --git a/dll/win32/CMakeLists.txt b/dll/win32/CMakeLists.txt index 24b2783315c..4d4a4b8633e 100644 --- a/dll/win32/CMakeLists.txt +++ b/dll/win32/CMakeLists.txt @@ -108,8 +108,8 @@ add_subdirectory(mssign32) add_subdirectory(mssip32) add_subdirectory(mstask) add_subdirectory(msvcrt) -#add_subdirectory(msvcrt20) FIX spec2def -#add_subdirectory(msvcrt40) FIX spec2def +add_subdirectory(msvcrt20) +add_subdirectory(msvcrt40) add_subdirectory(msvfw32) add_subdirectory(msvidc32) add_subdirectory(mswsock) diff --git a/dll/win32/browseui/CMakeLists.txt b/dll/win32/browseui/CMakeLists.txt index ca4c40817d3..12d9899635b 100644 --- a/dll/win32/browseui/CMakeLists.txt +++ b/dll/win32/browseui/CMakeLists.txt @@ -66,4 +66,5 @@ add_importlibs(browseui kernel32 ntdll) +add_pch(browseui precomp.h) add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/browseui/aclmulti.cpp b/dll/win32/browseui/aclmulti.cpp index c34fe5bf4fc..69df206b1a8 100644 --- a/dll/win32/browseui/aclmulti.cpp +++ b/dll/win32/browseui/aclmulti.cpp @@ -19,18 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "wine/debug.h" -#include "aclmulti.h" +#include "precomp.h" WINE_DEFAULT_DEBUG_CHANNEL(browseui); diff --git a/dll/win32/browseui/addressband.cpp b/dll/win32/browseui/addressband.cpp index 0010f5f2daf..9b9e744618a 100644 --- a/dll/win32/browseui/addressband.cpp +++ b/dll/win32/browseui/addressband.cpp @@ -21,17 +21,7 @@ /* Implements the navigation band of the cabinet window */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "addressband.h" +#include "precomp.h" /* TODO: diff --git a/dll/win32/browseui/addresseditbox.cpp b/dll/win32/browseui/addresseditbox.cpp index 7d36ff3dfd7..2b96d4148f3 100644 --- a/dll/win32/browseui/addresseditbox.cpp +++ b/dll/win32/browseui/addresseditbox.cpp @@ -21,17 +21,7 @@ /* This class handles the combo box of the address band. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "addresseditbox.h" +#include "precomp.h" /* TODO: Add auto completion support diff --git a/dll/win32/browseui/bandproxy.cpp b/dll/win32/browseui/bandproxy.cpp index 1d75e436af4..3d14b646c45 100644 --- a/dll/win32/browseui/bandproxy.cpp +++ b/dll/win32/browseui/bandproxy.cpp @@ -24,19 +24,7 @@ Used by the address band to dispatch navigation changes to the main browser obje TODO: */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "bandproxy.h" +#include "precomp.h" CBandProxy::CBandProxy() { diff --git a/dll/win32/browseui/bandsite.cpp b/dll/win32/browseui/bandsite.cpp index c3e2e6ad1a0..a751281c8be 100644 --- a/dll/win32/browseui/bandsite.cpp +++ b/dll/win32/browseui/bandsite.cpp @@ -19,18 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "wine/debug.h" -#include "bandsite.h" +#include "precomp.h" WINE_DEFAULT_DEBUG_CHANNEL(browseui); diff --git a/dll/win32/browseui/bandsitemenu.cpp b/dll/win32/browseui/bandsitemenu.cpp index fee02afb225..6258b03e587 100644 --- a/dll/win32/browseui/bandsitemenu.cpp +++ b/dll/win32/browseui/bandsitemenu.cpp @@ -19,18 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "bandsitemenu.h" -#include "wine/debug.h" +#include "precomp.h" WINE_DEFAULT_DEBUG_CHANNEL(browseui); diff --git a/dll/win32/browseui/basebar.cpp b/dll/win32/browseui/basebar.cpp index 1e4caaaa594..db7bed557f3 100644 --- a/dll/win32/browseui/basebar.cpp +++ b/dll/win32/browseui/basebar.cpp @@ -21,15 +21,7 @@ /* This class knows how to contain base bar site in a cabinet window. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* Base bar that contains a vertical or horizontal explorer band. It also diff --git a/dll/win32/browseui/basebarsite.cpp b/dll/win32/browseui/basebarsite.cpp index 730c26dbd3e..08498c09ed0 100644 --- a/dll/win32/browseui/basebarsite.cpp +++ b/dll/win32/browseui/basebarsite.cpp @@ -22,15 +22,7 @@ Base bar that contains a vertical or horizontal explorer band. It also provides resizing abilities. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* TODO: diff --git a/dll/win32/browseui/brandband.cpp b/dll/win32/browseui/brandband.cpp index a33eb7ca563..892a8fe7ab8 100644 --- a/dll/win32/browseui/brandband.cpp +++ b/dll/win32/browseui/brandband.cpp @@ -22,19 +22,7 @@ Implements the logo band of a cabinet window. Most remarkable feature is the animation. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "brandband.h" +#include "precomp.h" /* TODO: diff --git a/dll/win32/browseui/browseui.cpp b/dll/win32/browseui/browseui.cpp index cea61760b90..752a5726889 100644 --- a/dll/win32/browseui/browseui.cpp +++ b/dll/win32/browseui/browseui.cpp @@ -18,26 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "aclmulti.h" -#include "addressband.h" -#include "addresseditbox.h" -#include "bandproxy.h" -#include "bandsite.h" -#include "bandsitemenu.h" -#include "brandband.h" -#include "internettoolbar.h" +#include "precomp.h" WINE_DEFAULT_DEBUG_CHANNEL(browseui); diff --git a/dll/win32/browseui/browseuiord.cpp b/dll/win32/browseui/browseuiord.cpp index 7f3ac3b3c79..cbbe93547ae 100644 --- a/dll/win32/browseui/browseuiord.cpp +++ b/dll/win32/browseui/browseuiord.cpp @@ -18,12 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" extern DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter); diff --git a/dll/win32/browseui/commonbrowser.cpp b/dll/win32/browseui/commonbrowser.cpp index 87e4b7b8a04..5543e5924a2 100644 --- a/dll/win32/browseui/commonbrowser.cpp +++ b/dll/win32/browseui/commonbrowser.cpp @@ -18,19 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "commonbrowser.h" +#include "precomp.h" CCommonBrowser::CCommonBrowser() { diff --git a/dll/win32/browseui/globalfoldersettings.cpp b/dll/win32/browseui/globalfoldersettings.cpp index 73ef09345d6..e042aa2d2c1 100644 --- a/dll/win32/browseui/globalfoldersettings.cpp +++ b/dll/win32/browseui/globalfoldersettings.cpp @@ -18,19 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "globalfoldersettings.h" +#include "precomp.h" CGlobalFolderSettings::CGlobalFolderSettings() { diff --git a/dll/win32/browseui/internettoolbar.cpp b/dll/win32/browseui/internettoolbar.cpp index bfad8a5bd9c..d0e69944b6c 100644 --- a/dll/win32/browseui/internettoolbar.cpp +++ b/dll/win32/browseui/internettoolbar.cpp @@ -22,20 +22,7 @@ Implements a class that knows how to hold and manage the menu band, brand band, toolbar, and address band for an explorer window */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "internettoolbar.h" +#include "precomp.h" // navigation controls and menubar just send a message to parent window /* diff --git a/dll/win32/browseui/precomp.h b/dll/win32/browseui/precomp.h new file mode 100644 index 00000000000..263499d0325 --- /dev/null +++ b/dll/win32/browseui/precomp.h @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" +#include "wine/debug.h" +#include "aclmulti.h" +#include "addressband.h" +#include "addresseditbox.h" +#include "bandproxy.h" +#include "bandsite.h" +#include "bandsitemenu.h" +#include "brandband.h" +#include "internettoolbar.h" +#include "commonbrowser.h" +#include "globalfoldersettings.h" +#include "regtreeoptions.h" +#include "newatlinterfaces.h" +#include "utility.h" diff --git a/dll/win32/browseui/regtreeoptions.cpp b/dll/win32/browseui/regtreeoptions.cpp index 11009327f73..a9ae73c6399 100644 --- a/dll/win32/browseui/regtreeoptions.cpp +++ b/dll/win32/browseui/regtreeoptions.cpp @@ -18,19 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "regtreeoptions.h" +#include "precomp.h" CRegTreeOptions::CRegTreeOptions() { diff --git a/dll/win32/browseui/shellbrowser.cpp b/dll/win32/browseui/shellbrowser.cpp index 758f2aa2dbd..b050772af9f 100644 --- a/dll/win32/browseui/shellbrowser.cpp +++ b/dll/win32/browseui/shellbrowser.cpp @@ -18,23 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "resource.h" -#include "newatlinterfaces.h" +#include "precomp.h" /* TODO: diff --git a/dll/win32/browseui/toolsband.cpp b/dll/win32/browseui/toolsband.cpp index dd7d0f76ce6..c472f6943ea 100644 --- a/dll/win32/browseui/toolsband.cpp +++ b/dll/win32/browseui/toolsband.cpp @@ -21,43 +21,12 @@ /* Implements the toolbar band of a cabinet window */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* TODO: **Fix GetBandInfo to calculate size correctly */ -static const int gBackCommandID = 0xa121; -static const int gForwardCommandID = 0xa122; -static const int gUpLevelCommandID = 0xa022; -static const int gSearchCommandID = 1003; -static const int gFoldersCommandID = 1004; -static const int gMoveToCommandID = 0x701f; -static const int gCopyToCommandID = 0x701e; -static const int gDeleteCommandID = 0x7011; -static const int gUndoCommandID = 0x701b; -static const int gViewsCommandID = 0x7031; -static const int gStopCommandID = 1010; -static const int gRefreshCommandID = 0xa220; -static const int gHomeCommandID = 1012; -static const int gMapDriveCommandID = 41089; -static const int gDisconnectCommandID = 41090; -static const int gFavoritesCommandID = 1015; -static const int gHistoryCommandID = 1016; -static const int gFullScreenCommandID = 1017; -static const int gPropertiesCommandID = 0x7013; -static const int gCutCommandID = 0x7018; -static const int gCopyCommandID = 0x7019; -static const int gPasteCommandID = 0x701a; -static const int gFolderOptionsCommandID = 41251; class CToolsBand : public CWindowImpl, diff --git a/dll/win32/browseui/travellog.cpp b/dll/win32/browseui/travellog.cpp index d05daa27175..83821b74760 100644 --- a/dll/win32/browseui/travellog.cpp +++ b/dll/win32/browseui/travellog.cpp @@ -40,16 +40,7 @@ TODO: Implement Revert */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" class CTravelEntry : public CComObjectRootEx, diff --git a/dll/win32/browseui/utility.cpp b/dll/win32/browseui/utility.cpp index dd1367367f7..9ade3fc36e5 100644 --- a/dll/win32/browseui/utility.cpp +++ b/dll/win32/browseui/utility.cpp @@ -1,6 +1,5 @@ -#include -#include "utility.h" +#include "precomp.h" void *operator new(size_t size) { diff --git a/dll/win32/dbghelp/CMakeLists.txt b/dll/win32/dbghelp/CMakeLists.txt index 59eacd22aba..6107df2401a 100644 --- a/dll/win32/dbghelp/CMakeLists.txt +++ b/dll/win32/dbghelp/CMakeLists.txt @@ -52,6 +52,7 @@ target_link_libraries(dbghelp ${PSEH_LIB} oldnames) +add_pch(dbghelp dbghelp_private.h) add_importlibs(dbghelp psapi version msvcrt kernel32 ntdll) add_importlib_target(dbghelp.spec) add_cd_file(TARGET dbghelp DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/jscript/CMakeLists.txt b/dll/win32/jscript/CMakeLists.txt index 27afb3d6f0c..d346e64a206 100644 --- a/dll/win32/jscript/CMakeLists.txt +++ b/dll/win32/jscript/CMakeLists.txt @@ -59,5 +59,6 @@ add_importlibs(jscript kernel32 ntdll) +add_pch(jscript jscript.h) add_dependencies(jscript jsglobal) add_cd_file(TARGET jscript DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/kernel32/CMakeLists.txt b/dll/win32/kernel32/CMakeLists.txt index d60988f39c4..6fbb71e4649 100644 --- a/dll/win32/kernel32/CMakeLists.txt +++ b/dll/win32/kernel32/CMakeLists.txt @@ -1,9 +1,6 @@ add_definitions(-D_KERNEL32_) -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x600) - include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys) set_rc_compiler() @@ -11,102 +8,87 @@ set_rc_compiler() spec2def(kernel32.dll kernel32.spec) list(APPEND SOURCE - debug/debugger.c - debug/output.c - except/except.c - file/backup.c - file/bintype.c - file/cnotify.c - file/copy.c - file/create.c - file/curdir.c - file/delete.c - file/deviceio.c - file/dir.c - file/dosdev.c - file/file.c - file/find.c - file/hardlink.c - file/iocompl.c - file/lfile.c - file/lock.c - file/mailslot.c - file/move.c - file/npipe.c - file/pipe.c - file/rw.c - file/tape.c - file/volume.c - mem/global.c - mem/heap.c - mem/isbad.c - mem/local.c - mem/procmem.c - mem/resnotify.c - mem/section.c - mem/virtual.c - misc/actctx.c - misc/atom.c - misc/casemap.c - misc/chartype.c - misc/collation.c - misc/comm.c - misc/commdcb.c - misc/computername.c - misc/console.c - misc/dllmain.c - misc/env.c - misc/error.c - misc/fold.c - misc/format_msg.c - misc/handle.c - misc/lang.c - misc/lcformat.c - misc/ldr.c - misc/lzexpand.c - misc/muldiv.c - misc/nls.c - misc/perfcnt.c - misc/power.c - misc/profile.c - misc/recovery.c - misc/res.c - misc/sortkey.c - misc/stubs.c - misc/sysinfo.c - misc/time.c - misc/timerqueue.c - misc/toolhelp.c - misc/utils.c - misc/version.c - process/cmdline.c - process/procsup.c - process/job.c - process/proc.c - process/session.c - string/lstring.c - synch/condvar.c - synch/critical.c - synch/event.c - synch/mutex.c - synch/sem.c - synch/timer.c - synch/wait.c - thread/fiber.c - thread/fls.c - thread/thread.c - thread/tls.c + client/appcache.c + client/atom.c + client/compname.c + client/debugger.c + client/dllmain.c + client/environ.c + client/except.c + client/fiber.c + client/handle.c + client/heapmem.c + client/job.c + client/loader.c + client/perfcnt.c + client/power.c + client/proc.c + client/resntfy.c + client/session.c + client/synch.c + client/sysinfo.c + client/time.c + client/timerqueue.c + client/toolhelp.c + client/utils.c + client/thread.c + client/vdm.c + client/version.c + client/virtmem.c + client/vista.c + client/file/backup.c + client/file/bintype.c + client/file/cnotify.c + client/file/copy.c + client/file/console.c + client/file/create.c + client/file/curdir.c + client/file/delete.c + client/file/deviceio.c + client/file/dir.c + client/file/dosdev.c + client/file/file.c + client/file/filemap.c + client/file/find.c + client/file/hardlink.c + client/file/iocompl.c + client/file/lfile.c + client/file/lock.c + client/file/mailslot.c + client/file/move.c + client/file/npipe.c + client/file/pipe.c + client/file/rw.c + client/file/tape.c + client/file/volume.c + wine/actctx.c + wine/comm.c + wine/lzexpand.c + wine/muldiv.c + wine/profile.c + wine/res.c + wine/timezone.c + winnls/string/casemap.c + winnls/string/chartype.c + winnls/string/collation.c + winnls/string/fold.c + winnls/string/format_msg.c + winnls/string/lang.c + winnls/string/lcformat.c + winnls/string/lstring.c + winnls/string/nls.c + winnls/string/sortkey.c kernel32.rc ${CMAKE_CURRENT_BINARY_DIR}/kernel32.def) if(ARCH MATCHES i386) list(APPEND SOURCE - thread/i386/fiber.S - thread/i386/thread.S) + client/i386/fiber.S + client/i386/thread.S) elseif(ARCH MATCHES amd64) list(APPEND SOURCE - thread/amd64/fiber.S - thread/amd64/thread.S) + client/amd64/fiber.S + client/amd64/thread.S) endif(ARCH MATCHES i386) add_library(kernel32 SHARED ${SOURCE}) @@ -114,7 +96,7 @@ add_library(kernel32 SHARED ${SOURCE}) set_entrypoint(kernel32 DllMain@12) set_image_base(kernel32 ${baseaddress_kernel32}) -target_link_libraries(kernel32 chkstk ${PSEH_LIB}) +target_link_libraries(kernel32 wine chkstk ${PSEH_LIB}) add_importlibs(kernel32 ntdll) add_pch(kernel32 k32.h) diff --git a/dll/win32/kernel32/client/amd64/fiber.S b/dll/win32/kernel32/client/amd64/fiber.S new file mode 100644 index 00000000000..14fdfa5f713 --- /dev/null +++ b/dll/win32/kernel32/client/amd64/fiber.S @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32//kernel32/client/amd64/fiber.S + * PURPOSE: Fiber context switch code for the amd64 architecture + * PROGRAMMER: + */ + +#include + +PUBLIC BaseFiberStartup +.PROC BaseFiberStartup + UNIMPLEMENTED BaseFiberStartup + /* FIXME: TODO */ + ret + +.ENDP BaseFiberStartup + + +PUBLIC SwitchToFiber + +SwitchToFiber: + UNIMPLEMENTED BaseFiberStartup + /* FIXME: TODO */ + ret + +END diff --git a/dll/win32/kernel32/thread/amd64/thread.S b/dll/win32/kernel32/client/amd64/thread.S similarity index 100% rename from dll/win32/kernel32/thread/amd64/thread.S rename to dll/win32/kernel32/client/amd64/thread.S diff --git a/dll/win32/kernel32/client/appcache.c b/dll/win32/kernel32/client/appcache.c new file mode 100644 index 00000000000..abe500fdab1 --- /dev/null +++ b/dll/win32/kernel32/client/appcache.c @@ -0,0 +1,166 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/kernel32/client/appcache.c + * PURPOSE: Application Compatibility Cache + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* TYPES **********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* + * @unimplemented + */ +NTSTATUS +WINAPI +BasepCheckBadapp(int a, wchar_t *Str, int b, int c, int d, int e, int f, int g, int h) +{ + STUB; + return STATUS_NOT_IMPLEMENTED; +} + +/* + * @unimplemented + */ +VOID +WINAPI +BaseDumpAppcompatCache(VOID) +{ + STUB; +} + +/* + * @unimplemented + */ +VOID +WINAPI +BaseFlushAppcompatCache(VOID) +{ + STUB; +} + +/* + * @unimplemented + */ +VOID +WINAPI +BasepFreeAppCompatData(PVOID A, PVOID B) +{ + STUB; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +BaseIsAppcompatInfrastructureDisabled(VOID) +{ + STUB; + return TRUE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +BaseCheckAppcompatCache(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + PULONG Unknown4) +{ + STUB; + if (Unknown4) *Unknown4 = 0; + return TRUE; +} + +/* + * @unimplemented + */ +VOID +WINAPI +BaseUpdateAppcompatCache(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +{ + STUB; +} + +NTSTATUS +WINAPI +BaseCleanupAppcompatCache(VOID) +{ + STUB; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +WINAPI +BaseCleanupAppcompatCacheSupport(PVOID pUnknown) +{ + STUB; + return STATUS_NOT_IMPLEMENTED; +} + +BOOL +WINAPI +BaseInitAppcompatCache(VOID) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +BaseInitAppcompatCacheSupport(VOID) +{ + STUB; + return FALSE; +} + +PVOID +WINAPI +GetComPlusPackageInstallStatus(VOID) +{ + STUB; + return NULL; +} + +BOOL +WINAPI +SetComPlusPackageInstallStatus(LPVOID lpInfo) +{ + STUB; + return FALSE; +} + + /* + * @unimplemented + */ +VOID +WINAPI +SetTermsrvAppInstallMode(IN BOOL bInstallMode) +{ + STUB; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +TermsrvAppInstallMode(VOID) +{ + STUB; + return FALSE; +} diff --git a/dll/win32/kernel32/client/atom.c b/dll/win32/kernel32/client/atom.c new file mode 100644 index 00000000000..420bab81908 --- /dev/null +++ b/dll/win32/kernel32/client/atom.c @@ -0,0 +1,599 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/atom.c + * PURPOSE: Atom functions + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES ******************************************************************/ +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +PRTL_ATOM_TABLE BaseLocalAtomTable = NULL; + +/* FUNCTIONS *****************************************************************/ + +PVOID +WINAPI +InternalInitAtomTable(VOID) +{ + /* Create or return the local table */ + if (!BaseLocalAtomTable) RtlCreateAtomTable(0, &BaseLocalAtomTable); + return BaseLocalAtomTable; +} + +ATOM +WINAPI +InternalAddAtom(BOOLEAN Local, + BOOLEAN Unicode, + LPCSTR AtomName) +{ + NTSTATUS Status; + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + PUNICODE_STRING AtomNameString; + ATOM Atom = INVALID_ATOM; + + /* Check if it's an integer atom */ + if ((ULONG_PTR)AtomName <= 0xFFFF) + { + /* Convert the name to an atom */ + Atom = (ATOM)PtrToShort((PVOID)AtomName); + if (Atom >= MAXINTATOM) + { + /* Fail, atom number too large */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return INVALID_ATOM; + } + + /* Return it */ + return Atom; + } + else + { + /* Check if this is a unicode atom */ + if (Unicode) + { + /* Use a unicode string */ + AtomNameString = &UnicodeString; + RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName); + Status = STATUS_SUCCESS; + } + else + { + /* Use an ansi string */ + RtlInitAnsiString(&AnsiString, AtomName ); + + /* Check if we can abuse the TEB */ + if (AnsiString.MaximumLength > 260) + { + /* We can't, allocate a new string */ + AtomNameString = &UnicodeString; + Status = RtlAnsiStringToUnicodeString(AtomNameString, + &AnsiString, + TRUE); + } + else + { + /* We can! Get the TEB String */ + AtomNameString = &NtCurrentTeb()->StaticUnicodeString; + + /* Convert it into the TEB */ + Status = RtlAnsiStringToUnicodeString(AtomNameString, + &AnsiString, + FALSE); + } + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return Atom; + } + } + + /* Check if we're doing local add */ + if (Local) + { + /* Do a local add */ + Status = RtlAddAtomToAtomTable(InternalInitAtomTable(), + AtomNameString->Buffer, + &Atom); + } + else + { + /* Do a global add */ + Status = NtAddAtom(AtomNameString->Buffer, + AtomNameString->Length, + &Atom); + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status); + + /* Check if we were non-static ANSI */ + if (!(Unicode) && (AtomNameString == &UnicodeString)) + { + /* Free the allocated buffer */ + RtlFreeUnicodeString(AtomNameString); + } + + /* Return the atom */ + return Atom; +} + +ATOM +WINAPI +InternalFindAtom(BOOLEAN Local, + BOOLEAN Unicode, + LPCSTR AtomName) +{ + NTSTATUS Status; + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + PUNICODE_STRING AtomNameString; + ATOM Atom = INVALID_ATOM; + + /* Check if it's an integer atom */ + if ((ULONG_PTR)AtomName <= 0xFFFF) + { + /* Convert the name to an atom */ + Atom = (ATOM)PtrToShort((PVOID)AtomName); + if (Atom >= MAXINTATOM) + { + /* Fail, atom number too large */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + DPRINT1("Invalid atom\n"); + } + + /* Return it */ + return Atom; + } + else + { + /* Check if this is a unicode atom */ + if (Unicode) + { + /* Use a unicode string */ + AtomNameString = &UnicodeString; + RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName); + Status = STATUS_SUCCESS; + } + else + { + /* Use an ansi string */ + RtlInitAnsiString(&AnsiString, AtomName); + + /* Check if we can abuse the TEB */ + if (AnsiString.MaximumLength > 260) + { + /* We can't, allocate a new string */ + AtomNameString = &UnicodeString; + Status = RtlAnsiStringToUnicodeString(AtomNameString, + &AnsiString, + TRUE); + } + else + { + /* We can! Get the TEB String */ + AtomNameString = &NtCurrentTeb()->StaticUnicodeString; + + /* Convert it into the TEB */ + Status = RtlAnsiStringToUnicodeString(AtomNameString, + &AnsiString, + FALSE); + } + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed\n"); + BaseSetLastNTError(Status); + return Atom; + } + } + + /* Check if we're doing local lookup */ + if (Local) + { + /* Do a local lookup */ + Status = RtlLookupAtomInAtomTable(InternalInitAtomTable(), + AtomNameString->Buffer, + &Atom); + } + else + { + /* Do a global search */ + if (!AtomNameString->Length) + { + /* This is illegal in win32 */ + DPRINT1("No name given\n"); + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + else + { + /* Call the global function */ + Status = NtFindAtom(AtomNameString->Buffer, + AtomNameString->Length, + &Atom); + } + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status); + + /* Check if we were non-static ANSI */ + if (!(Unicode) && (AtomNameString == &UnicodeString)) + { + /* Free the allocated buffer */ + RtlFreeUnicodeString(AtomNameString); + } + + /* Return the atom */ + return Atom; +} + +ATOM +WINAPI +InternalDeleteAtom(BOOLEAN Local, + ATOM Atom) +{ + NTSTATUS Status; + + /* Validate it */ + if (Atom >= MAXINTATOM) + { + /* Check if it's a local delete */ + if (Local) + { + /* Delete it locally */ + Status = RtlDeleteAtomFromAtomTable(InternalInitAtomTable(), Atom); + } + else + { + /* Delete it globall */ + Status = NtDeleteAtom(Atom); + } + + /* Check for success */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return INVALID_ATOM; + } + } + + /* Return failure */ + return 0; +} + +UINT +WINAPI +InternalGetAtomName(BOOLEAN Local, + BOOLEAN Unicode, + ATOM Atom, + LPSTR AtomName, + DWORD Size) +{ + NTSTATUS Status; + DWORD RetVal = 0; + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + PVOID TempBuffer = NULL; + PWSTR AtomNameString; + ULONG AtomInfoLength; + ULONG AtomNameLength; + PATOM_BASIC_INFORMATION AtomInfo; + + /* Normalize the size as not to overflow */ + if (!Unicode && Size > 0x7000) Size = 0x7000; + + /* Make sure it's valid too */ + if (!Size) + { + BaseSetLastNTError(STATUS_BUFFER_OVERFLOW); + return 0; + } + if (!Atom) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return 0; + } + + /* Check if this is a global query */ + if (Local) + { + /* Set the query length */ + AtomNameLength = Size * sizeof(WCHAR); + + /* If it's unicode, just keep the name */ + if (Unicode) + { + AtomNameString = (PWSTR)AtomName; + } + else + { + /* Allocate memory for the ansi buffer */ + TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + AtomNameLength); + AtomNameString = TempBuffer; + } + + /* Query the name */ + Status = RtlQueryAtomInAtomTable(InternalInitAtomTable(), + Atom, + NULL, + NULL, + AtomNameString, + &AtomNameLength); + } + else + { + /* We're going to do a global query, so allocate a buffer */ + AtomInfoLength = sizeof(ATOM_BASIC_INFORMATION) + + (Size * sizeof(WCHAR)); + AtomInfo = TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + AtomInfoLength); + + if (!AtomInfo) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return 0; + } + + /* Query the name */ + Status = NtQueryInformationAtom(Atom, + AtomBasicInformation, + AtomInfo, + AtomInfoLength, + &AtomInfoLength); + if (NT_SUCCESS(Status)) + { + /* Success. Update the length and get the name */ + AtomNameLength = (ULONG)AtomInfo->NameLength; + AtomNameString = AtomInfo->Name; + } + } + + /* Check for global success */ + if (NT_SUCCESS(Status)) + { + /* Check if it was unicode */ + if (Unicode) + { + /* We return the length in chars */ + RetVal = AtomNameLength / sizeof(WCHAR); + + /* Copy the memory if this was a global query */ + if (AtomNameString != (PWSTR)AtomName) + { + RtlMoveMemory(AtomName, AtomNameString, AtomNameLength); + } + + /* And null-terminate it if the buffer was too large */ + if (RetVal < Size) + { + ((PWCHAR)AtomName)[RetVal] = UNICODE_NULL; + } + } + else + { + /* First create a unicode string with our data */ + UnicodeString.Buffer = AtomNameString; + UnicodeString.Length = (USHORT)AtomNameLength; + UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length + + sizeof(WCHAR)); + + /* Now prepare an ansi string for conversion */ + AnsiString.Buffer = AtomName; + AnsiString.Length = 0; + AnsiString.MaximumLength = (USHORT)Size; + + /* Convert it */ + Status = RtlUnicodeStringToAnsiString(&AnsiString, + &UnicodeString, + FALSE); + + /* Return the length */ + if (NT_SUCCESS(Status)) RetVal = AnsiString.Length; + } + } + + /* Free the temporary buffer if we have one */ + if (TempBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer); + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + DPRINT("Failed: %lx\n", Status); + BaseSetLastNTError(Status); + } + + /* Return length */ + return RetVal; +} + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +ATOM +WINAPI +GlobalAddAtomA(LPCSTR lpString) +{ + return InternalAddAtom(FALSE, FALSE, lpString); +} + +/* + * @implemented + */ +ATOM +WINAPI +GlobalAddAtomW(LPCWSTR lpString) +{ + return InternalAddAtom(FALSE, TRUE, (LPSTR)lpString); +} + +/* + * @implemented + */ +ATOM +WINAPI +GlobalDeleteAtom(ATOM nAtom) +{ + return InternalDeleteAtom(FALSE, nAtom); +} + +/* + * @implemented + */ +ATOM +WINAPI +GlobalFindAtomA(LPCSTR lpString) +{ + return InternalFindAtom(FALSE, FALSE, lpString); +} + +/* + * @implemented + */ +ATOM +WINAPI +GlobalFindAtomW(LPCWSTR lpString) +{ + return InternalFindAtom(FALSE, TRUE, (LPSTR)lpString); +} + +/* + * @implemented + */ +UINT +WINAPI +GlobalGetAtomNameA(ATOM nAtom, + LPSTR lpBuffer, + int nSize) +{ + return InternalGetAtomName(FALSE, FALSE, nAtom, lpBuffer, (DWORD)nSize); +} + +/* + * @implemented + */ +UINT +WINAPI +GlobalGetAtomNameW(ATOM nAtom, + LPWSTR lpBuffer, + int nSize) +{ + return InternalGetAtomName(FALSE, + TRUE, + nAtom, + (LPSTR)lpBuffer, + (DWORD)nSize); +} + +/* + * @implemented + */ +BOOL +WINAPI +InitAtomTable(DWORD nSize) +{ + /* Normalize size */ + if (nSize < 4 || nSize > 511) nSize = 37; + + DPRINT("Here\n"); + return NT_SUCCESS(RtlCreateAtomTable(nSize, &BaseLocalAtomTable)); +} + +/* + * @implemented + */ +ATOM +WINAPI +AddAtomA(LPCSTR lpString) +{ + return InternalAddAtom(TRUE, FALSE, lpString); +} + +/* + * @implemented + */ +ATOM +WINAPI +AddAtomW(LPCWSTR lpString) +{ + return InternalAddAtom(TRUE, TRUE, (LPSTR)lpString); +} + +/* + * @implemented + */ +ATOM +WINAPI +DeleteAtom(ATOM nAtom) +{ + return InternalDeleteAtom(TRUE, nAtom); +} + +/* + * @implemented + */ +ATOM +WINAPI +FindAtomA(LPCSTR lpString) +{ + return InternalFindAtom(TRUE, FALSE, lpString); +} + +/* + * @implemented + */ +ATOM +WINAPI +FindAtomW(LPCWSTR lpString) +{ + return InternalFindAtom(TRUE, TRUE, (LPSTR)lpString); + +} + +/* + * @implemented + */ +UINT +WINAPI +GetAtomNameA(ATOM nAtom, + LPSTR lpBuffer, + int nSize) +{ + return InternalGetAtomName(TRUE, FALSE, nAtom, lpBuffer, (DWORD)nSize); +} + +/* + * @implemented + */ +UINT +WINAPI +GetAtomNameW(ATOM nAtom, + LPWSTR lpBuffer, + int nSize) +{ + return InternalGetAtomName(TRUE, + TRUE, + nAtom, + (LPSTR)lpBuffer, + (DWORD)nSize); +} +/* EOF */ diff --git a/dll/win32/kernel32/client/compname.c b/dll/win32/kernel32/client/compname.c new file mode 100644 index 00000000000..4b404e1f501 --- /dev/null +++ b/dll/win32/kernel32/client/compname.c @@ -0,0 +1,634 @@ +/* + * ReactOS kernel + * Copyright (C) 2003 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: Computer name functions + * FILE: lib/kernel32/misc/computername.c + * PROGRAMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +static +BOOL +GetComputerNameFromRegistry(LPWSTR RegistryKey, + LPWSTR ValueNameStr, + LPWSTR lpBuffer, + LPDWORD nSize) +{ + PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + ULONG KeyInfoSize; + ULONG ReturnSize; + NTSTATUS Status; + + RtlInitUnicodeString(&KeyName, RegistryKey); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenKey(&KeyHandle, + KEY_READ, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + *nSize * sizeof(WCHAR); + KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize); + if (KeyInfo == NULL) + { + ZwClose(KeyHandle); + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + + RtlInitUnicodeString(&ValueName, ValueNameStr); + + Status = ZwQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + KeyInfo, + KeyInfoSize, + &ReturnSize); + + ZwClose(KeyHandle); + + if (!NT_SUCCESS(Status)) + { + *nSize = ReturnSize; + goto failed; + } + + if (KeyInfo->Type != REG_SZ) + { + Status = STATUS_UNSUCCESSFUL; + goto failed; + } + + if (!lpBuffer || *nSize < (KeyInfo->DataLength / sizeof(WCHAR))) + { + *nSize = ReturnSize; + Status = STATUS_BUFFER_OVERFLOW; + goto failed; + } + + *nSize = KeyInfo->DataLength / sizeof(WCHAR) - 1; + RtlCopyMemory(lpBuffer, KeyInfo->Data, KeyInfo->DataLength); + lpBuffer[*nSize] = 0; + + RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo); + + return TRUE; + +failed: + RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo); + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetComputerNameExW(COMPUTER_NAME_FORMAT NameType, + LPWSTR lpBuffer, + LPDWORD nSize) +{ + UNICODE_STRING ResultString; + UNICODE_STRING DomainPart; + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + BOOL ret = TRUE; + DWORD HostSize; + + switch (NameType) + { + case ComputerNameNetBIOS: + return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Control\\ComputerName\\ComputerName", + L"ComputerName", + lpBuffer, + nSize); + + case ComputerNameDnsDomain: + return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Services\\Tcpip\\Parameters", + L"Domain", + lpBuffer, + nSize); + + case ComputerNameDnsFullyQualified: + ResultString.Length = 0; + ResultString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR); + ResultString.Buffer = lpBuffer; + + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + RtlInitUnicodeString(&DomainPart, NULL); + + QueryTable[0].Name = L"HostName"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &DomainPart; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, + L"\\Registry\\Machine\\System" + L"\\CurrentControlSet\\Services\\Tcpip" + L"\\Parameters", + QueryTable, + NULL, + NULL); + + if (NT_SUCCESS(Status)) + { + Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart); + HostSize = DomainPart.Length; + + if (!NT_SUCCESS(Status)) + { + ret = FALSE; + } + + RtlAppendUnicodeToString(&ResultString, L"."); + RtlFreeUnicodeString(&DomainPart); + + RtlInitUnicodeString(&DomainPart, NULL); + QueryTable[0].Name = L"Domain"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &DomainPart; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, + L"\\Registry\\Machine\\System" + L"\\CurrentControlSet\\Services\\Tcpip" + L"\\Parameters", + QueryTable, + NULL, + NULL); + + if (NT_SUCCESS(Status)) + { + Status = RtlAppendUnicodeStringToString(&ResultString, &DomainPart); + if ((!NT_SUCCESS(Status)) || (!ret)) + { + *nSize = HostSize + DomainPart.Length; + SetLastError(ERROR_MORE_DATA); + RtlFreeUnicodeString(&DomainPart); + return FALSE; + } + RtlFreeUnicodeString(&DomainPart); + *nSize = ResultString.Length / sizeof(WCHAR) - 1; + return TRUE; + } + } + return FALSE; + + case ComputerNameDnsHostname: + return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Services\\Tcpip\\Parameters", + L"Hostname", + lpBuffer, + nSize); + + case ComputerNamePhysicalDnsDomain: + return GetComputerNameFromRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Services\\Tcpip\\Parameters", + L"Domain", + lpBuffer, + nSize); + + /* XXX Redo these */ + case ComputerNamePhysicalDnsFullyQualified: + return GetComputerNameExW(ComputerNameDnsFullyQualified, + lpBuffer, + nSize); + + case ComputerNamePhysicalDnsHostname: + return GetComputerNameExW(ComputerNameDnsHostname, + lpBuffer, + nSize); + + case ComputerNamePhysicalNetBIOS: + return GetComputerNameExW(ComputerNameNetBIOS, + lpBuffer, + nSize); + + case ComputerNameMax: + return FALSE; + } + + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetComputerNameExA(COMPUTER_NAME_FORMAT NameType, + LPSTR lpBuffer, + LPDWORD nSize) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + BOOL Result; + PWCHAR TempBuffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, *nSize * sizeof(WCHAR) ); + + if (!TempBuffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + AnsiString.MaximumLength = (USHORT)*nSize; + AnsiString.Length = 0; + AnsiString.Buffer = lpBuffer; + + Result = GetComputerNameExW(NameType, TempBuffer, nSize); + + if (Result) + { + UnicodeString.MaximumLength = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR); + UnicodeString.Length = (USHORT)*nSize * sizeof(WCHAR) + sizeof(WCHAR); + UnicodeString.Buffer = TempBuffer; + + RtlUnicodeStringToAnsiString(&AnsiString, + &UnicodeString, + FALSE); + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer); + + return Result; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize) +{ + BOOL ret; + ret = GetComputerNameExA(ComputerNameNetBIOS, lpBuffer, lpnSize); + if(!ret && GetLastError() == ERROR_MORE_DATA) + SetLastError(ERROR_BUFFER_OVERFLOW); + return ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize) +{ + BOOL ret; + ret=GetComputerNameExW(ComputerNameNetBIOS, lpBuffer, lpnSize); + if(!ret && GetLastError() == ERROR_MORE_DATA) + SetLastError(ERROR_BUFFER_OVERFLOW); + return ret; +} + + +/* + * @implemented + */ +static +BOOL +IsValidComputerName(COMPUTER_NAME_FORMAT NameType, + LPCWSTR lpComputerName) +{ + PWCHAR p; + ULONG Length; + + /* FIXME: do verification according to NameType */ + + Length = 0; + p = (PWCHAR)lpComputerName; + + while (*p != 0) + { + if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' || + *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' || + *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' || + *p == L'{' || *p == L'}' || *p == L'~')) + return FALSE; + + Length++; + p++; + } + + if (Length == 0 || Length > MAX_COMPUTERNAME_LENGTH) + return FALSE; + + return TRUE; +} + + +static +BOOL +SetComputerNameToRegistry(LPCWSTR RegistryKey, + LPCWSTR ValueNameStr, + LPCWSTR lpBuffer) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + NTSTATUS Status; + + RtlInitUnicodeString(&KeyName, RegistryKey); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&KeyHandle, + KEY_WRITE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + RtlInitUnicodeString(&ValueName, ValueNameStr); + + Status = NtSetValueKey(KeyHandle, + &ValueName, + 0, + REG_SZ, + (PVOID)lpBuffer, + (wcslen (lpBuffer) + 1) * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + { + ZwClose(KeyHandle); + BaseSetLastNTError(Status); + return FALSE; + } + + NtFlushKey(KeyHandle); + ZwClose(KeyHandle); + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetComputerNameA(LPCSTR lpComputerName) +{ + return SetComputerNameExA(ComputerNamePhysicalNetBIOS, lpComputerName); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetComputerNameW(LPCWSTR lpComputerName) +{ + return SetComputerNameExW(ComputerNamePhysicalNetBIOS, lpComputerName); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetComputerNameExA(COMPUTER_NAME_FORMAT NameType, + LPCSTR lpBuffer) +{ + UNICODE_STRING Buffer; + BOOL bResult; + + RtlCreateUnicodeStringFromAsciiz(&Buffer, (LPSTR)lpBuffer); + + bResult = SetComputerNameExW(NameType, Buffer.Buffer); + + RtlFreeUnicodeString(&Buffer); + + return bResult; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetComputerNameExW(COMPUTER_NAME_FORMAT NameType, + LPCWSTR lpBuffer) +{ + if (!IsValidComputerName(NameType, lpBuffer)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch( NameType ) + { + case ComputerNamePhysicalDnsDomain: + return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Services\\Tcpip\\Parameters", + L"Domain", + lpBuffer); + + case ComputerNamePhysicalDnsHostname: + return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Services\\Tcpip\\Parameters", + L"Hostname", + lpBuffer); + + case ComputerNamePhysicalNetBIOS: + return SetComputerNameToRegistry(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Control\\ComputerName\\ComputerName", + L"ComputerName", + lpBuffer); + + default: + SetLastError (ERROR_INVALID_PARAMETER); + return FALSE; + } +} + + +/* + * @implemented + */ +BOOL +WINAPI +DnsHostnameToComputerNameA(LPCSTR Hostname, + LPSTR ComputerName, + LPDWORD nSize) +{ + DWORD len; + + DPRINT("(%s, %p, %p)\n", Hostname, ComputerName, nSize); + + if (!Hostname || !nSize) + return FALSE; + + len = lstrlenA(Hostname); + + if (len > MAX_COMPUTERNAME_LENGTH) + len = MAX_COMPUTERNAME_LENGTH; + + if (*nSize < len) + { + *nSize = len; + return FALSE; + } + + if (!ComputerName) return FALSE; + + memcpy(ComputerName, Hostname, len); + ComputerName[len + 1] = 0; + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +DnsHostnameToComputerNameW(LPCWSTR hostname, + LPWSTR computername, + LPDWORD size) +{ + DWORD len; + + DPRINT("(%s, %p, %p): stub\n", hostname, computername, size); + + if (!hostname || !size) return FALSE; + len = lstrlenW(hostname); + + if (len > MAX_COMPUTERNAME_LENGTH) + len = MAX_COMPUTERNAME_LENGTH; + + if (*size < len) + { + *size = len; + return FALSE; + } + if (!computername) return FALSE; + + memcpy(computername, hostname, len * sizeof(WCHAR)); + computername[len + 1] = 0; + return TRUE; +} + +DWORD +WINAPI +AddLocalAlternateComputerNameA(LPSTR lpName, PNTSTATUS Status) +{ + STUB; + return 0; +} + +DWORD +WINAPI +AddLocalAlternateComputerNameW(LPWSTR lpName, PNTSTATUS Status) +{ + STUB; + return 0; +} + +DWORD +WINAPI +EnumerateLocalComputerNamesA(PVOID pUnknown, DWORD Size, LPSTR lpBuffer, LPDWORD lpnSize) +{ + STUB; + return ERROR_CALL_NOT_IMPLEMENTED; +} + +DWORD +WINAPI +EnumerateLocalComputerNamesW(PVOID pUnknown, DWORD Size, LPWSTR lpBuffer, LPDWORD lpnSize) +{ + STUB; + return ERROR_CALL_NOT_IMPLEMENTED; +} + +DWORD +WINAPI +RemoveLocalAlternateComputerNameA(LPSTR lpName, DWORD Unknown) +{ + STUB; + return ERROR_CALL_NOT_IMPLEMENTED; +} + +DWORD +WINAPI +RemoveLocalAlternateComputerNameW(LPWSTR lpName, DWORD Unknown) +{ + STUB; + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetLocalPrimaryComputerNameA(IN DWORD Unknown1, + IN DWORD Unknown2) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetLocalPrimaryComputerNameW(IN DWORD Unknown1, + IN DWORD Unknown2) +{ + STUB; + return FALSE; +} + + +/* EOF */ diff --git a/dll/win32/kernel32/client/debugger.c b/dll/win32/kernel32/client/debugger.c new file mode 100644 index 00000000000..e4e695ef46f --- /dev/null +++ b/dll/win32/kernel32/client/debugger.c @@ -0,0 +1,956 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/kernel32/debug/debugger.c + * PURPOSE: Wrappers for the NT Debug Implementation + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +typedef struct _DBGSS_THREAD_DATA +{ + struct _DBGSS_THREAD_DATA *Next; + HANDLE ThreadHandle; + HANDLE ProcessHandle; + DWORD ProcessId; + DWORD ThreadId; + BOOLEAN HandleMarked; +} DBGSS_THREAD_DATA, *PDBGSS_THREAD_DATA; + +#define DbgSsSetThreadData(d) \ + NtCurrentTeb()->DbgSsReserved[0] = d + +#define DbgSsGetThreadData() \ + ((PDBGSS_THREAD_DATA)NtCurrentTeb()->DbgSsReserved[0]) + +/* PRIVATE FUNCTIONS *********************************************************/ + +static +HANDLE +K32CreateDBMonMutex(void) +{ + static SID_IDENTIFIER_AUTHORITY siaNTAuth = {SECURITY_NT_AUTHORITY}; + static SID_IDENTIFIER_AUTHORITY siaWorldAuth = {SECURITY_WORLD_SID_AUTHORITY}; + HANDLE hMutex; + + /* SIDs to be used in the DACL */ + PSID psidSystem = NULL; + PSID psidAdministrators = NULL; + PSID psidEveryone = NULL; + + /* buffer for the DACL */ + PVOID pDaclBuf = NULL; + + /* minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE + headers. We'll add the size of SIDs when we'll know it + */ + SIZE_T nDaclBufSize = + sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - + sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart)) * 3; + + /* security descriptor of the mutex */ + SECURITY_DESCRIPTOR sdMutexSecurity; + + /* attributes of the mutex object we'll create */ + SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs), + &sdMutexSecurity, + TRUE}; + + NTSTATUS nErrCode; + + /* first, try to open the mutex */ + hMutex = OpenMutexW (SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, + TRUE, + L"DBWinMutex"); + + if(hMutex != NULL) + { + /* success */ + return hMutex; + } + /* error other than the mutex not being found */ + else if(GetLastError() != ERROR_FILE_NOT_FOUND) + { + /* failure */ + return NULL; + } + + /* if the mutex doesn't exist, create it */ + + /* first, set up the mutex security */ + /* allocate the NT AUTHORITY\SYSTEM SID */ + nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + &psidSystem); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* allocate the BUILTIN\Administrators SID */ + nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, + 0, + 0, + 0, + 0, + 0, + &psidAdministrators); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* allocate the Everyone SID */ + nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + &psidEveryone); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* allocate space for the SIDs too */ + nDaclBufSize += RtlLengthSid(psidSystem); + nDaclBufSize += RtlLengthSid(psidAdministrators); + nDaclBufSize += RtlLengthSid(psidEveryone); + + /* allocate the buffer for the DACL */ + pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize); + + /* failure */ + if(pDaclBuf == NULL) goto l_Cleanup; + + /* create the DACL */ + nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* grant the minimum required access to Everyone */ + nErrCode = RtlAddAccessAllowedAce(pDaclBuf, + ACL_REVISION, + SYNCHRONIZE | + READ_CONTROL | + MUTANT_QUERY_STATE, + psidEveryone); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* grant full access to BUILTIN\Administrators */ + nErrCode = RtlAddAccessAllowedAce(pDaclBuf, + ACL_REVISION, + MUTANT_ALL_ACCESS, + psidAdministrators); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* grant full access to NT AUTHORITY\SYSTEM */ + nErrCode = RtlAddAccessAllowedAce(pDaclBuf, + ACL_REVISION, + MUTANT_ALL_ACCESS, + psidSystem); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* create the security descriptor */ + nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity, + SECURITY_DESCRIPTOR_REVISION); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* set the descriptor's DACL to the ACL we created */ + nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity, + TRUE, + pDaclBuf, + FALSE); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; + + /* create the mutex */ + hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex"); + +l_Cleanup: + /* free the buffers */ + if(pDaclBuf) GlobalFree(pDaclBuf); + if(psidEveryone) RtlFreeSid(psidEveryone); + if(psidAdministrators) RtlFreeSid(psidAdministrators); + if(psidSystem) RtlFreeSid(psidSystem); + + return hMutex; +} + +VOID +WINAPI +SaveThreadHandle(IN DWORD dwProcessId, + IN DWORD dwThreadId, + IN HANDLE hThread) +{ + PDBGSS_THREAD_DATA ThreadData; + + /* Allocate a thread structure */ + ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(DBGSS_THREAD_DATA)); + if (!ThreadData) return; + + /* Fill it out */ + ThreadData->ThreadHandle = hThread; + ThreadData->ProcessId = dwProcessId; + ThreadData->ThreadId = dwThreadId; + ThreadData->ProcessHandle = NULL; + ThreadData->HandleMarked = FALSE; + + /* Link it */ + ThreadData->Next = DbgSsGetThreadData(); + DbgSsSetThreadData(ThreadData); +} + +VOID +WINAPI +SaveProcessHandle(IN DWORD dwProcessId, + IN HANDLE hProcess) +{ + PDBGSS_THREAD_DATA ThreadData; + + /* Allocate a thread structure */ + ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(DBGSS_THREAD_DATA)); + if (!ThreadData) return; + + /* Fill it out */ + ThreadData->ProcessHandle = hProcess; + ThreadData->ProcessId = dwProcessId; + ThreadData->ThreadId = 0; + ThreadData->ThreadHandle = NULL; + ThreadData->HandleMarked = FALSE; + + /* Link it */ + ThreadData->Next = DbgSsGetThreadData(); + DbgSsSetThreadData(ThreadData); +} + +VOID +WINAPI +MarkThreadHandle(IN DWORD dwThreadId) +{ + PDBGSS_THREAD_DATA ThreadData; + + /* Loop all thread data events */ + for (ThreadData = DbgSsGetThreadData(); ThreadData; ThreadData = ThreadData->Next) + { + /* Check if this one matches */ + if (ThreadData->ThreadId == dwThreadId) + { + /* Mark the structure and break out */ + ThreadData->HandleMarked = TRUE; + break; + } + } +} + +VOID +WINAPI +MarkProcessHandle(IN DWORD dwProcessId) +{ + PDBGSS_THREAD_DATA ThreadData; + + /* Loop all thread data events */ + for (ThreadData = DbgSsGetThreadData(); ThreadData; ThreadData = ThreadData->Next) + { + /* Check if this one matches */ + if ((ThreadData->ProcessId == dwProcessId) && !(ThreadData->ThreadId)) + { + /* Mark the structure and break out */ + ThreadData->HandleMarked = TRUE; + break; + } + } +} + +VOID +WINAPI +RemoveHandles(IN DWORD dwProcessId, + IN DWORD dwThreadId) +{ + PDBGSS_THREAD_DATA *ThreadData; + PDBGSS_THREAD_DATA ThisData; + + /* Loop all thread data events */ + ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved; + for (ThisData = *ThreadData; ThisData; ThisData = ThisData->Next) + { + /* Check if this one matches */ + if ((ThisData->HandleMarked) && + ((ThisData->ProcessId == dwProcessId) || (ThisData->ThreadId == dwThreadId))) + { + /* Close open handles */ + if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle); + if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle); + + /* Unlink the thread data */ + *ThreadData = ThisData->Next; + + /* Free it*/ + RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData); + } + else + { + /* Move to the next one */ + ThreadData = &ThisData->Next; + } + } +} + +VOID +WINAPI +CloseAllProcessHandles(IN DWORD dwProcessId) +{ + PDBGSS_THREAD_DATA *ThreadData; + PDBGSS_THREAD_DATA ThisData; + + /* Loop all thread data events */ + ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved; + for (ThisData = *ThreadData; ThisData; ThisData = ThisData->Next) + { + /* Check if this one matches */ + if (ThisData->ProcessId == dwProcessId) + { + /* Close open handles */ + if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle); + if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle); + + /* Unlink the thread data */ + *ThreadData = ThisData->Next; + + /* Free it*/ + RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData); + } + else + { + /* Move to the next one */ + ThreadData = &ThisData->Next; + } + } +} + +HANDLE +WINAPI +ProcessIdToHandle(IN DWORD dwProcessId) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + CLIENT_ID ClientId; + + /* If we don't have a PID, look it up */ + if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId(); + + /* Open a handle to the process */ + ClientId.UniqueThread = NULL; + ClientId.UniqueProcess = UlongToHandle(dwProcessId); + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + Status = NtOpenProcess(&Handle, + PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | + PROCESS_VM_WRITE | PROCESS_VM_READ | + PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return 0; + } + + /* Return the handle */ + return Handle; +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +CheckRemoteDebuggerPresent(IN HANDLE hProcess, + OUT PBOOL pbDebuggerPresent) +{ + HANDLE DebugPort; + NTSTATUS Status; + + /* Make sure we have an output and process*/ + if (!(pbDebuggerPresent) || !(hProcess)) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Check if the process has a debug object/port */ + Status = NtQueryInformationProcess(hProcess, + ProcessDebugPort, + (PVOID)&DebugPort, + sizeof(HANDLE), + NULL); + if (NT_SUCCESS(Status)) + { + /* Return the current state */ + *pbDebuggerPresent = DebugPort != NULL; + return TRUE; + } + + /* Otherwise, fail */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +ContinueDebugEvent(IN DWORD dwProcessId, + IN DWORD dwThreadId, + IN DWORD dwContinueStatus) +{ + CLIENT_ID ClientId; + NTSTATUS Status; + + /* Set the Client ID */ + ClientId.UniqueProcess = (HANDLE)dwProcessId; + ClientId.UniqueThread = (HANDLE)dwThreadId; + + /* Continue debugging */ + Status = DbgUiContinue(&ClientId, dwContinueStatus); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Remove the process/thread handles */ + RemoveHandles(dwProcessId, dwThreadId); + + /* Success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DebugActiveProcess(IN DWORD dwProcessId) +{ + NTSTATUS Status, Status1; + HANDLE Handle; + + /* Connect to the debugger */ + Status = DbgUiConnectToDbg(); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + /* Get the process handle */ + Handle = ProcessIdToHandle(dwProcessId); + if (!Handle) return FALSE; + + /* Now debug the process */ + Status = DbgUiDebugActiveProcess(Handle); + + /* Close the handle since we're done */ + Status1 = NtClose(Handle); + ASSERT(NT_SUCCESS(Status1)); + + /* Check if debugging worked */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DebugActiveProcessStop(IN DWORD dwProcessId) +{ + NTSTATUS Status, Status1; + HANDLE Handle; + + /* Get the process handle */ + Handle = ProcessIdToHandle(dwProcessId); + if (!Handle) return FALSE; + + /* Close all the process handles */ + CloseAllProcessHandles(dwProcessId); + + /* Now stop debgging the process */ + Status = DbgUiStopDebugging(Handle); + Status1 = NtClose(Handle); + ASSERT(NT_SUCCESS(Status1)); + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + + /* Success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DebugBreakProcess(IN HANDLE Process) +{ + NTSTATUS Status; + + /* Send the breakin request */ + Status = DbgUiIssueRemoteBreakin(Process); + if(!NT_SUCCESS(Status)) + { + /* Failure */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DebugSetProcessKillOnExit(IN BOOL KillOnExit) +{ + HANDLE Handle; + NTSTATUS Status; + ULONG State; + + /* Get the debug object */ + Handle = DbgUiGetThreadDebugObject(); + if (!Handle) + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_HANDLE); + return FALSE; + } + + /* Now set the kill-on-exit state */ + State = KillOnExit != 0; + Status = NtSetInformationDebugObject(Handle, + DebugObjectKillProcessOnExitInformation, + &State, + sizeof(State), + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +IsDebuggerPresent(VOID) +{ + return (BOOL)NtCurrentPeb()->BeingDebugged; +} + +/* + * @implemented + */ +BOOL +WINAPI +WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, + IN DWORD dwMilliseconds) +{ + LARGE_INTEGER WaitTime; + PLARGE_INTEGER Timeout; + DBGUI_WAIT_STATE_CHANGE WaitStateChange; + NTSTATUS Status; + + /* Convert to NT Timeout */ + Timeout = BaseFormatTimeOut(&WaitTime, dwMilliseconds); + + /* Loop while we keep getting interrupted */ + do + { + /* Call the native API */ + Status = DbgUiWaitStateChange(&WaitStateChange, Timeout); + } while ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC)); + + /* Check if the wait failed */ + if (!(NT_SUCCESS(Status)) || (Status == DBG_UNABLE_TO_PROVIDE_HANDLE)) + { + /* Set the error code and quit */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Check if we timed out */ + if (Status == STATUS_TIMEOUT) + { + /* Fail with a timeout error */ + SetLastError(ERROR_SEM_TIMEOUT); + return FALSE; + } + + /* Convert the structure */ + Status = DbgUiConvertStateChangeStructure(&WaitStateChange, lpDebugEvent); + if (!NT_SUCCESS(Status)) + { + /* Set the error code and quit */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Check what kind of event this was */ + switch (lpDebugEvent->dwDebugEventCode) + { + /* New thread was created */ + case CREATE_THREAD_DEBUG_EVENT: + + /* Setup the thread data */ + SaveThreadHandle(lpDebugEvent->dwProcessId, + lpDebugEvent->dwThreadId, + lpDebugEvent->u.CreateThread.hThread); + break; + + /* New process was created */ + case CREATE_PROCESS_DEBUG_EVENT: + + /* Setup the process data */ + SaveProcessHandle(lpDebugEvent->dwProcessId, + lpDebugEvent->u.CreateProcessInfo.hProcess); + + /* Setup the thread data */ + SaveThreadHandle(lpDebugEvent->dwProcessId, + lpDebugEvent->dwThreadId, + lpDebugEvent->u.CreateProcessInfo.hThread); + break; + + /* Process was exited */ + case EXIT_PROCESS_DEBUG_EVENT: + + /* Mark the thread data as such and fall through */ + MarkProcessHandle(lpDebugEvent->dwProcessId); + + /* Thread was exited */ + case EXIT_THREAD_DEBUG_EVENT: + + /* Mark the thread data */ + MarkThreadHandle(lpDebugEvent->dwThreadId); + break; + + /* Nothing to do */ + case EXCEPTION_DEBUG_EVENT: + case LOAD_DLL_DEBUG_EVENT: + case UNLOAD_DLL_DEBUG_EVENT: + case OUTPUT_DEBUG_STRING_EVENT: + case RIP_EVENT: + break; + + /* Fail anything else */ + default: + return FALSE; + } + + /* Return success */ + return TRUE; +} + +/* + * @implemented + */ +VOID +WINAPI +OutputDebugStringA(IN LPCSTR _OutputString) +{ + _SEH2_TRY + { + ULONG_PTR a_nArgs[2]; + + a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1); + a_nArgs[1] = (ULONG_PTR)_OutputString; + + /* send the string to the user-mode debugger */ + RaiseException(DBG_PRINTEXCEPTION_C, 0, 2, a_nArgs); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* no user-mode debugger: try the systemwide debug message monitor, or the + kernel debugger as a last resort */ + + /* mutex used to synchronize invocations of OutputDebugString */ + static HANDLE s_hDBMonMutex = NULL; + /* true if we already attempted to open/create the mutex */ + static BOOL s_bDBMonMutexTriedOpen = FALSE; + + /* local copy of the mutex handle */ + volatile HANDLE hDBMonMutex = s_hDBMonMutex; + /* handle to the Section of the shared buffer */ + volatile HANDLE hDBMonBuffer = NULL; + + /* pointer to the mapped view of the shared buffer. It consist of the current + process id followed by the message string */ + struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL; + + /* event: signaled by the debug message monitor when OutputDebugString can write + to the shared buffer */ + volatile HANDLE hDBMonBufferReady = NULL; + + /* event: to be signaled by OutputDebugString when it's done writing to the + shared buffer */ + volatile HANDLE hDBMonDataReady = NULL; + + /* mutex not opened, and no previous attempts to open/create it */ + if(hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen) + { + /* open/create the mutex */ + hDBMonMutex = K32CreateDBMonMutex(); + /* store the handle */ + s_hDBMonMutex = hDBMonMutex; + } + + _SEH2_TRY + { + volatile PCHAR a_cBuffer = NULL; + + /* opening the mutex failed */ + if(hDBMonMutex == NULL) + { + /* remember next time */ + s_bDBMonMutexTriedOpen = TRUE; + } + /* opening the mutex succeeded */ + else + { + do + { + /* synchronize with other invocations of OutputDebugString */ + WaitForSingleObject(hDBMonMutex, INFINITE); + + /* buffer of the system-wide debug message monitor */ + hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE, L"DBWIN_BUFFER"); + + /* couldn't open the buffer: send the string to the kernel debugger */ + if(hDBMonBuffer == NULL) break; + + /* map the buffer */ + pDBMonBuffer = MapViewOfFile(hDBMonBuffer, + SECTION_MAP_READ | SECTION_MAP_WRITE, + 0, + 0, + 0); + + /* couldn't map the buffer: send the string to the kernel debugger */ + if(pDBMonBuffer == NULL) break; + + /* open the event signaling that the buffer can be accessed */ + hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY"); + + /* couldn't open the event: send the string to the kernel debugger */ + if(hDBMonBufferReady == NULL) break; + + /* open the event to be signaled when the buffer has been filled */ + hDBMonDataReady = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"DBWIN_DATA_READY"); + } + while(0); + + /* we couldn't connect to the system-wide debug message monitor: send the + string to the kernel debugger */ + if(hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex); + } + + _SEH2_TRY + { + /* size of the current output block */ + volatile SIZE_T nRoundLen; + + /* size of the remainder of the string */ + volatile SIZE_T nOutputStringLen; + + /* output the whole string */ + nOutputStringLen = strlen(_OutputString); + + do + { + /* we're connected to the debug monitor: + write the current block to the shared buffer */ + if(hDBMonDataReady) + { + /* wait a maximum of 10 seconds for the debug monitor + to finish processing the shared buffer */ + if(WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0) + { + /* timeout or failure: give up */ + break; + } + + /* write the process id into the buffer */ + pDBMonBuffer->ProcessId = GetCurrentProcessId(); + + /* write only as many bytes as they fit in the buffer */ + if(nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1)) + nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1; + else + nRoundLen = nOutputStringLen; + + /* copy the current block into the buffer */ + memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen); + + /* null-terminate the current block */ + pDBMonBuffer->Buffer[nRoundLen] = 0; + + /* signal that the data contains meaningful data and can be read */ + SetEvent(hDBMonDataReady); + } + /* else, send the current block to the kernel debugger */ + else + { + /* output in blocks of 512 characters */ + a_cBuffer = (CHAR*)HeapAlloc(GetProcessHeap(), 0, 512); + + if (!a_cBuffer) + { + DbgPrint("OutputDebugStringA: Failed\n"); + break; + } + + /* write a maximum of 511 bytes */ + if(nOutputStringLen > 510) + nRoundLen = 510; + else + nRoundLen = nOutputStringLen; + + /* copy the current block */ + memcpy(a_cBuffer, _OutputString, nRoundLen); + + /* null-terminate the current block */ + a_cBuffer[nRoundLen] = 0; + + /* send the current block to the kernel debugger */ + DbgPrint("%s", a_cBuffer); + + if (a_cBuffer) + { + HeapFree(GetProcessHeap(), 0, a_cBuffer); + a_cBuffer = NULL; + } + } + + /* move to the next block */ + _OutputString += nRoundLen; + nOutputStringLen -= nRoundLen; + } + /* repeat until the string has been fully output */ + while (nOutputStringLen > 0); + } + /* ignore access violations and let other exceptions fall through */ + _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + if (a_cBuffer) + HeapFree(GetProcessHeap(), 0, a_cBuffer); + + /* string copied verbatim from Microsoft's kernel32.dll */ + DbgPrint("\nOutputDebugString faulted during output\n"); + } + _SEH2_END; + } + _SEH2_FINALLY + { + /* close all the still open resources */ + if(hDBMonBufferReady) CloseHandle(hDBMonBufferReady); + if(pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer); + if(hDBMonBuffer) CloseHandle(hDBMonBuffer); + if(hDBMonDataReady) CloseHandle(hDBMonDataReady); + + /* leave the critical section */ + if(hDBMonDataReady != NULL) + ReleaseMutex(hDBMonMutex); + } + _SEH2_END; + } + _SEH2_END; +} + +/* + * @implemented + */ +VOID +WINAPI +OutputDebugStringW(IN LPCWSTR OutputString) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + NTSTATUS Status; + + /* convert the string in ANSI */ + RtlInitUnicodeString(&UnicodeString, OutputString); + Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE); + + /* OutputDebugStringW always prints something, even if conversion fails */ + if (!NT_SUCCESS(Status)) AnsiString.Buffer = ""; + + /* Output the converted string */ + OutputDebugStringA(AnsiString.Buffer); + + /* free the converted string */ + if (NT_SUCCESS(Status)) RtlFreeAnsiString(&AnsiString); +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/dllmain.c b/dll/win32/kernel32/client/dllmain.c new file mode 100644 index 00000000000..61677f0e4ca --- /dev/null +++ b/dll/win32/kernel32/client/dllmain.c @@ -0,0 +1,462 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/dllmain.c + * PURPOSE: Initialization + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Aleksey Bragin (aleksey@reactos.org) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +extern UNICODE_STRING SystemDirectory; +extern UNICODE_STRING WindowsDirectory; + +PBASE_STATIC_SERVER_DATA BaseStaticServerData; + +BOOLEAN BaseRunningInServerProcess; + +WCHAR BaseDefaultPathBuffer[6140]; + +HANDLE BaseNamedObjectDirectory; +HANDLE hProcessHeap = NULL; +HMODULE hCurrentModule = NULL; +HMODULE kernel32_handle = NULL; +HANDLE hBaseDir = NULL; +PPEB Peb; +ULONG SessionId; +BOOL ConsoleInitialized = FALSE; +UNICODE_STRING BaseWindowsDirectory, BaseWindowsSystemDirectory; +static BOOL DllInitialized = FALSE; + +BOOL WINAPI +DllMain(HANDLE hInst, + DWORD dwReason, + LPVOID lpReserved); + +/* Critical section for various kernel32 data structures */ +RTL_CRITICAL_SECTION BaseDllDirectoryLock; +RTL_CRITICAL_SECTION ConsoleLock; + +extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); +extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); +extern PHANDLER_ROUTINE InitialHandler[1]; +extern PHANDLER_ROUTINE* CtrlHandlers; +extern ULONG NrCtrlHandlers; +extern ULONG NrAllocatedHandlers; +extern BOOL FASTCALL NlsInit(VOID); +extern VOID FASTCALL NlsUninit(VOID); +BOOLEAN InWindows = FALSE; + +HANDLE +WINAPI +DuplicateConsoleHandle(HANDLE hConsole, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions); + +#define WIN_OBJ_DIR L"\\Windows" +#define SESSION_DIR L"\\Sessions" + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +WINAPI +BaseGetNamedObjectDirectory(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, + &BaseStaticServerData->NamedObjectDirectory, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenDirectoryObject(&BaseNamedObjectDirectory, + DIRECTORY_ALL_ACCESS & + ~(DELETE | WRITE_DAC | WRITE_OWNER), + &ObjectAttributes); + if (!NT_SUCCESS(Status)) return Status; + + DPRINT("Opened BNO: %lx\n", BaseNamedObjectDirectory); + return Status; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +BaseQueryModuleData(IN LPSTR ModuleName, + IN LPSTR Unknown, + IN PVOID Unknown2, + IN PVOID Unknown3, + IN PVOID Unknown4) +{ + DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n", + ModuleName, + Unknown, + Unknown2, + Unknown3, + Unknown4); + return FALSE; +} + +/* + * @unimplemented + */ +NTSTATUS +WINAPI +BaseProcessInitPostImport(VOID) +{ + /* FIXME: Initialize TS pointers */ + return STATUS_SUCCESS; +} + +BOOL +WINAPI +BasepInitConsole(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + BOOLEAN NotConsole = FALSE; + PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; + LPCWSTR ExeName; + + WCHAR lpTest[MAX_PATH]; + GetModuleFileNameW(NULL, lpTest, MAX_PATH); + DPRINT("BasepInitConsole for : %S\n", lpTest); + DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n", + Parameters->ConsoleHandle, Parameters->StandardInput, + Parameters->StandardOutput, Parameters->StandardError); + + /* We have nothing to do if this isn't a console app... */ + if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem != + IMAGE_SUBSYSTEM_WINDOWS_CUI) + { + DPRINT("Image is not a console application\n"); + Parameters->ConsoleHandle = NULL; + Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE; + } + else + { + /* Assume one is needed */ + Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE; + Request.Data.AllocConsoleRequest.Visible = TRUE; + + /* Handle the special flags given to us by BasepInitializeEnvironment */ + if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS) + { + /* No console to create */ + DPRINT("No console to create\n"); + Parameters->ConsoleHandle = NULL; + Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE; + } + else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE) + { + /* We'll get the real one soon */ + DPRINT("Creating new console\n"); + Parameters->ConsoleHandle = NULL; + } + else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW) + { + /* We'll get the real one soon */ + DPRINT("Creating new invisible console\n"); + Parameters->ConsoleHandle = NULL; + Request.Data.AllocConsoleRequest.Visible = FALSE; + } + else + { + if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE) + { + Parameters->ConsoleHandle = 0; + } + DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle); + } + } + + /* Initialize Console Ctrl Handler and input EXE name */ + ConsoleInitialized = TRUE; + RtlInitializeCriticalSection(&ConsoleLock); + NrAllocatedHandlers = 1; + NrCtrlHandlers = 1; + CtrlHandlers = InitialHandler; + CtrlHandlers[0] = DefaultConsoleCtrlHandler; + + ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\'); + if (ExeName) + SetConsoleInputExeNameW(ExeName + 1); + + /* Now use the proper console handle */ + Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle; + + /* + * Normally, we should be connecting to the Console CSR Server... + * but we don't have one yet, so we will instead simply send a create + * console message to the Base Server. When we finally have a Console + * Server, this code should be changed to send connection data instead. + */ + CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE); + Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher; + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + DPRINT1("CSR Failed to give us a console\n"); + /* We're lying here, so at least the process can load... */ + return TRUE; + } + + if (NotConsole) return TRUE; + + /* We got the handles, let's set them */ + if ((Parameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console)) + { + /* If we already had some, don't use the new ones */ + if (!Parameters->StandardInput) + { + Parameters->StandardInput = Request.Data.AllocConsoleRequest.InputHandle; + } + if (!Parameters->StandardOutput) + { + Parameters->StandardOutput = Request.Data.AllocConsoleRequest.OutputHandle; + } + if (!Parameters->StandardError) + { + Parameters->StandardError = Request.Data.AllocConsoleRequest.OutputHandle; + } + } + + DPRINT("Console setup: %lx, %lx, %lx, %lx\n", + Parameters->ConsoleHandle, + Parameters->StandardInput, + Parameters->StandardOutput, + Parameters->StandardError); + return TRUE; +} + +BOOL +WINAPI +DllMain(HANDLE hDll, + DWORD dwReason, + LPVOID lpReserved) +{ + NTSTATUS Status; + ULONG Dummy; + ULONG DummySize = sizeof(Dummy); + WCHAR SessionDir[256]; + + DPRINT("DllMain(hInst %lx, dwReason %lu)\n", + hDll, dwReason); + + Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString; + + /* Cache the PEB and Session ID */ + Peb = NtCurrentPeb(); + SessionId = Peb->SessionId; + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + + /* Don't bother us for each thread */ + LdrDisableThreadCalloutsForDll((PVOID)hDll); + + /* Initialize default path to NULL */ + RtlInitUnicodeString(&BaseDefaultPath, NULL); + + /* Setup the right Object Directory path */ + if (!SessionId) + { + /* Use the raw path */ + wcscpy(SessionDir, WIN_OBJ_DIR); + } + else + { + /* Use the session path */ + swprintf(SessionDir, + L"%ws\\%ld%ws", + SESSION_DIR, + SessionId, + WIN_OBJ_DIR); + } + + /* Connect to the base server */ + DPRINT("Connecting to CSR...\n"); + Status = CsrClientConnectToServer(SessionDir, + InWindows ? 1 : 0, + &Dummy, + &DummySize, + &BaseRunningInServerProcess); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to connect to CSR (Status %lx)\n", Status); + ZwTerminateProcess(NtCurrentProcess(), Status); + return FALSE; + } + + /* Get the server data */ + ASSERT(Peb->ReadOnlyStaticServerData); + BaseStaticServerData = Peb->ReadOnlyStaticServerData[CSR_CONSOLE]; + ASSERT(BaseStaticServerData); + + /* Check if we are running a CSR Server */ + if (!BaseRunningInServerProcess) + { + /* Set the termination port for the thread */ + DPRINT("Creating new thread for CSR\n"); + CsrNewThread(); + } + + /* Initialize heap handle table */ + hProcessHeap = RtlGetProcessHeap(); + RtlInitializeHandleTable(0xFFFF, + sizeof(BASE_HEAP_HANDLE_ENTRY), + &BaseHeapHandleTable); + DPRINT("Heap: %p\n", hProcessHeap); + + /* Set HMODULE for our DLL */ + kernel32_handle = hCurrentModule = hDll; + + /* Set the directories */ + BaseWindowsDirectory = BaseStaticServerData->WindowsDirectory; + BaseWindowsSystemDirectory = BaseStaticServerData->WindowsSystemDirectory; + SystemDirectory = BaseWindowsSystemDirectory; + WindowsDirectory = BaseWindowsDirectory; + + /* Construct the default path (using the static buffer) */ + _snwprintf(BaseDefaultPathBuffer, sizeof(BaseDefaultPathBuffer) / sizeof(WCHAR), + L".;%wZ;%wZ\\system;%wZ;", &SystemDirectory, &WindowsDirectory, &WindowsDirectory); + + BaseDefaultPath.Buffer = BaseDefaultPathBuffer; + BaseDefaultPath.Length = wcslen(BaseDefaultPathBuffer) * sizeof(WCHAR); + BaseDefaultPath.MaximumLength = sizeof(BaseDefaultPathBuffer); + + /* Use remaining part of the default path buffer for the append path */ + BaseDefaultPathAppend.Buffer = (PWSTR)((ULONG_PTR)BaseDefaultPathBuffer + BaseDefaultPath.Length); + BaseDefaultPathAppend.Length = 0; + BaseDefaultPathAppend.MaximumLength = BaseDefaultPath.MaximumLength - BaseDefaultPath.Length; + + /* Initialize command line */ + InitCommandLines(); + + /* Open object base directory */ + Status = BaseGetNamedObjectDirectory(); + hBaseDir = BaseNamedObjectDirectory; + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open object base directory (Status %lx)\n", Status); + return FALSE; + } + + /* Initialize the DLL critical section */ + RtlInitializeCriticalSection(&BaseDllDirectoryLock); + + /* Initialize the National Language Support routines */ + if (!NlsInit()) + { + DPRINT1("NLS Init failed\n"); + return FALSE; + } + + /* Initialize Console Support */ + if (!BasepInitConsole()) + { + DPRINT1("Failure to set up console\n"); + return FALSE; + } + + /* Insert more dll attach stuff here! */ + DllInitialized = TRUE; + DPRINT("Initialization complete\n"); + break; + + case DLL_PROCESS_DETACH: + + DPRINT("DLL_PROCESS_DETACH\n"); + if (DllInitialized == TRUE) + { + /* Insert more dll detach stuff here! */ + NlsUninit(); + + /* Delete DLL critical section */ + if (ConsoleInitialized == TRUE) + { + ConsoleInitialized = FALSE; + RtlDeleteCriticalSection (&ConsoleLock); + } + RtlDeleteCriticalSection (&BaseDllDirectoryLock); + + /* Close object base directory */ + NtClose(hBaseDir); + } + break; + + default: + break; + } + + return TRUE; +} + +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef InterlockedExchange +#undef InterlockedExchangeAdd +#undef InterlockedCompareExchange + +LONG +WINAPI +InterlockedIncrement(IN OUT LONG volatile *lpAddend) +{ + return _InterlockedIncrement(lpAddend); +} + +LONG +WINAPI +InterlockedDecrement(IN OUT LONG volatile *lpAddend) +{ + return _InterlockedDecrement(lpAddend); +} + +#undef InterlockedExchange +LONG +WINAPI +InterlockedExchange(IN OUT LONG volatile *Target, + IN LONG Value) +{ + return _InterlockedExchange(Target, Value); +} + +LONG +WINAPI +InterlockedExchangeAdd(IN OUT LONG volatile *Addend, + IN LONG Value) +{ + return _InterlockedExchangeAdd(Addend, Value); +} + +LONG +WINAPI +InterlockedCompareExchange(IN OUT LONG volatile *Destination, + IN LONG Exchange, + IN LONG Comperand) +{ + return _InterlockedCompareExchange(Destination, Exchange, Comperand); +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/environ.c b/dll/win32/kernel32/client/environ.c new file mode 100644 index 00000000000..7564f7f9eef --- /dev/null +++ b/dll/win32/kernel32/client/environ.c @@ -0,0 +1,534 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/env.c + * PURPOSE: Environment functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Emanuele Aliberti + * Thomas Weidenmueller + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include + +#define NDEBUG +#include + + +/* FUNCTIONS ******************************************************************/ + +/* + * @implemented + */ +DWORD +WINAPI +GetEnvironmentVariableA ( + LPCSTR lpName, + LPSTR lpBuffer, + DWORD nSize + ) +{ + ANSI_STRING VarName; + ANSI_STRING VarValue; + UNICODE_STRING VarNameU; + UNICODE_STRING VarValueU; + NTSTATUS Status; + + /* initialize unicode variable name string */ + RtlInitAnsiString (&VarName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString (&VarNameU, + &VarName, + TRUE); + + /* initialize ansi variable value string */ + VarValue.Length = 0; + VarValue.MaximumLength = (USHORT)nSize; + VarValue.Buffer = lpBuffer; + + /* initialize unicode variable value string and allocate buffer */ + VarValueU.Length = 0; + if (nSize != 0) + { + VarValueU.MaximumLength = (USHORT)(nSize - 1) * sizeof(WCHAR); + VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + nSize * sizeof(WCHAR)); + if (VarValueU.Buffer != NULL) + { + /* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U + only terminates it if MaximumLength < Length! */ + VarValueU.Buffer[nSize - 1] = L'\0'; + } + } + else + { + VarValueU.MaximumLength = 0; + VarValueU.Buffer = NULL; + } + + if (VarValueU.Buffer != NULL || nSize == 0) + { + /* get unicode environment variable */ + Status = RtlQueryEnvironmentVariable_U (NULL, + &VarNameU, + &VarValueU); + if (!NT_SUCCESS(Status)) + { + /* free unicode buffer */ + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VarValueU.Buffer); + + /* free unicode variable name string */ + RtlFreeUnicodeString (&VarNameU); + + BaseSetLastNTError (Status); + if (Status == STATUS_BUFFER_TOO_SMALL) + { + return (VarValueU.Length / sizeof(WCHAR)) + 1; + } + else + { + return 0; + } + } + + /* convert unicode value string to ansi */ + RtlUnicodeStringToAnsiString (&VarValue, + &VarValueU, + FALSE); + + if (VarValueU.Buffer != NULL) + { + /* free unicode buffer */ + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VarValueU.Buffer); + } + + /* free unicode variable name string */ + RtlFreeUnicodeString (&VarNameU); + + return (VarValueU.Length / sizeof(WCHAR)); + } + else + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return 0; + } +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetEnvironmentVariableW ( + LPCWSTR lpName, + LPWSTR lpBuffer, + DWORD nSize + ) +{ + UNICODE_STRING VarName; + UNICODE_STRING VarValue; + NTSTATUS Status; + + RtlInitUnicodeString (&VarName, + lpName); + + VarValue.Length = 0; + VarValue.MaximumLength = (USHORT) (nSize ? nSize - 1 : 0) * sizeof(WCHAR); + VarValue.Buffer = lpBuffer; + + Status = RtlQueryEnvironmentVariable_U (NULL, + &VarName, + &VarValue); + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_BUFFER_TOO_SMALL) + { + return (VarValue.Length / sizeof(WCHAR)) + 1; + } + else + { + BaseSetLastNTError (Status); + return 0; + } + } + + if (nSize != 0) + { + /* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U + only terminates it if MaximumLength < Length */ + lpBuffer[VarValue.Length / sizeof(WCHAR)] = L'\0'; + } + + return (VarValue.Length / sizeof(WCHAR)); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetEnvironmentVariableA ( + LPCSTR lpName, + LPCSTR lpValue + ) +{ + ANSI_STRING VarName; + ANSI_STRING VarValue; + UNICODE_STRING VarNameU; + UNICODE_STRING VarValueU; + NTSTATUS Status; + + DPRINT("SetEnvironmentVariableA(Name '%s', Value '%s')\n", lpName, lpValue); + + RtlInitAnsiString (&VarName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString (&VarNameU, + &VarName, + TRUE); + + if (lpValue) + { + RtlInitAnsiString (&VarValue, + (LPSTR)lpValue); + RtlAnsiStringToUnicodeString (&VarValueU, + &VarValue, + TRUE); + + Status = RtlSetEnvironmentVariable (NULL, + &VarNameU, + &VarValueU); + + RtlFreeUnicodeString (&VarValueU); + } + else + { + Status = RtlSetEnvironmentVariable (NULL, + &VarNameU, + NULL); + } + RtlFreeUnicodeString (&VarNameU); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetEnvironmentVariableW ( + LPCWSTR lpName, + LPCWSTR lpValue + ) +{ + UNICODE_STRING VarName; + UNICODE_STRING VarValue; + NTSTATUS Status; + + DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue); + + RtlInitUnicodeString (&VarName, + lpName); + + RtlInitUnicodeString (&VarValue, + lpValue); + + Status = RtlSetEnvironmentVariable (NULL, + &VarName, + &VarValue); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +LPSTR +WINAPI +GetEnvironmentStringsA ( + VOID + ) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + PWCHAR EnvU; + PWCHAR PtrU; + ULONG Length; + PCHAR EnvPtr = NULL; + + EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment); + + if (EnvU == NULL) + return NULL; + + if (*EnvU == 0) + return NULL; + + /* get environment size */ + PtrU = EnvU; + while (*PtrU) + { + while (*PtrU) + PtrU++; + PtrU++; + } + Length = (ULONG)(PtrU - EnvU); + DPRINT("Length %lu\n", Length); + + /* allocate environment buffer */ + EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length + 1); + if (EnvPtr == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + DPRINT("EnvPtr %p\n", EnvPtr); + + /* convert unicode environment to ansi */ + UnicodeString.MaximumLength = (USHORT)Length * sizeof(WCHAR) + sizeof(WCHAR); + UnicodeString.Buffer = EnvU; + + AnsiString.MaximumLength = (USHORT)Length + 1; + AnsiString.Length = 0; + AnsiString.Buffer = EnvPtr; + + DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer); + + while (*(UnicodeString.Buffer)) + { + UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR); + UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR); + if (UnicodeString.Length > 0) + { + AnsiString.Length = 0; + AnsiString.MaximumLength = (USHORT)Length + 1 - (AnsiString.Buffer - EnvPtr); + + RtlUnicodeStringToAnsiString (&AnsiString, + &UnicodeString, + FALSE); + + AnsiString.Buffer += (AnsiString.Length + 1); + UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1); + } + } + *(AnsiString.Buffer) = 0; + + return EnvPtr; +} + + +/* + * @implemented + */ +LPWSTR +WINAPI +GetEnvironmentStringsW ( + VOID + ) +{ + return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment); +} + + +/* + * @implemented + */ +BOOL +WINAPI +FreeEnvironmentStringsA ( + LPSTR EnvironmentStrings + ) +{ + if (EnvironmentStrings == NULL) + return FALSE; + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + EnvironmentStrings); + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +FreeEnvironmentStringsW ( + LPWSTR EnvironmentStrings + ) +{ + return TRUE; +} + + +/* + * @implemented + */ +DWORD +WINAPI +ExpandEnvironmentStringsA ( + LPCSTR lpSrc, + LPSTR lpDst, + DWORD nSize + ) +{ + ANSI_STRING Source; + ANSI_STRING Destination; + UNICODE_STRING SourceU; + UNICODE_STRING DestinationU; + NTSTATUS Status; + ULONG Length = 0; + + RtlInitAnsiString (&Source, + (LPSTR)lpSrc); + Status = RtlAnsiStringToUnicodeString (&SourceU, + &Source, + TRUE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return 0; + } + + /* make sure we don't overflow the maximum ANSI_STRING size */ + if (nSize > 0x7fff) + nSize = 0x7fff; + + Destination.Length = 0; + Destination.MaximumLength = (USHORT)nSize; + Destination.Buffer = lpDst; + + DestinationU.Length = 0; + DestinationU.MaximumLength = (USHORT)nSize * sizeof(WCHAR); + DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + DestinationU.MaximumLength); + if (DestinationU.Buffer == NULL) + { + RtlFreeUnicodeString(&SourceU); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Status = RtlExpandEnvironmentStrings_U (NULL, + &SourceU, + &DestinationU, + &Length); + + RtlFreeUnicodeString (&SourceU); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + if (Status != STATUS_BUFFER_TOO_SMALL) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationU.Buffer); + return 0; + } + } + + RtlUnicodeStringToAnsiString (&Destination, + &DestinationU, + FALSE); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationU.Buffer); + + return (Length / sizeof(WCHAR)); +} + + +/* + * @implemented + */ +DWORD +WINAPI +ExpandEnvironmentStringsW ( + LPCWSTR lpSrc, + LPWSTR lpDst, + DWORD nSize + ) +{ + UNICODE_STRING Source; + UNICODE_STRING Destination; + NTSTATUS Status; + ULONG Length = 0; + + RtlInitUnicodeString (&Source, + (LPWSTR)lpSrc); + + /* make sure we don't overflow the maximum UNICODE_STRING size */ + if (nSize > 0x7fff) + nSize = 0x7fff; + + Destination.Length = 0; + Destination.MaximumLength = (USHORT)nSize * sizeof(WCHAR); + Destination.Buffer = lpDst; + + Status = RtlExpandEnvironmentStrings_U (NULL, + &Source, + &Destination, + &Length); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + if (Status != STATUS_BUFFER_TOO_SMALL) + return 0; + } + + return (Length / sizeof(WCHAR)); +} + +/* + * @implemented + */ +BOOL +WINAPI +SetEnvironmentStringsA(IN LPCH NewEnvironment) +{ + STUB; + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetEnvironmentStringsW(IN LPWCH NewEnvironment) +{ + STUB; + return FALSE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/except/except.c b/dll/win32/kernel32/client/except.c similarity index 72% rename from dll/win32/kernel32/except/except.c rename to dll/win32/kernel32/client/except.c index d57bd7a2e14..25fe140fbe7 100644 --- a/dll/win32/kernel32/except/except.c +++ b/dll/win32/kernel32/client/except.c @@ -16,91 +16,7 @@ #include LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = NULL; - -UINT -WINAPI -GetErrorMode(VOID) -{ - NTSTATUS Status; - UINT ErrMode; - - /* Query the current setting */ - Status = NtQueryInformationProcess(NtCurrentProcess(), - ProcessDefaultHardErrorMode, - (PVOID)&ErrMode, - sizeof(ErrMode), - NULL); - if (!NT_SUCCESS(Status)) - { - /* Fail if we couldn't query */ - SetLastErrorByStatus(Status); - return 0; - } - - /* Check if NOT failing critical errors was requested */ - if (ErrMode & SEM_FAILCRITICALERRORS) - { - /* Mask it out, since the native API works differently */ - ErrMode &= ~SEM_FAILCRITICALERRORS; - } - else - { - /* OR it if the caller didn't, due to different native semantics */ - ErrMode |= SEM_FAILCRITICALERRORS; - } - - /* Return the mode */ - return ErrMode; -} - -/* - * @implemented - */ -UINT -WINAPI -SetErrorMode(IN UINT uMode) -{ - UINT PrevErrMode, NewMode; - NTSTATUS Status; - - /* Get the previous mode */ - PrevErrMode = GetErrorMode(); - NewMode = uMode; - - /* Check if failing critical errors was requested */ - if (NewMode & SEM_FAILCRITICALERRORS) - { - /* Mask it out, since the native API works differently */ - NewMode &= ~SEM_FAILCRITICALERRORS; - } - else - { - /* OR it if the caller didn't, due to different native semantics */ - NewMode |= SEM_FAILCRITICALERRORS; - } - - /* Set the new mode */ - Status = NtSetInformationProcess(NtCurrentProcess(), - ProcessDefaultHardErrorMode, - (PVOID)&NewMode, - sizeof(NewMode)); - if(!NT_SUCCESS(Status)) SetLastErrorByStatus(Status); - - /* Return the previous mode */ - return PrevErrMode; -} - -/* - * @implemented - */ -LPTOP_LEVEL_EXCEPTION_FILTER -WINAPI -SetUnhandledExceptionFilter( - IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -{ - return InterlockedExchangePointer(&GlobalTopLevelExceptionFilter, - lpTopLevelExceptionFilter); -} +DWORD g_dwLastErrorToBreakOn; /* * Private helper function to lookup the module name from a given address. @@ -272,6 +188,42 @@ PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo) #endif } +UINT +WINAPI +GetErrorMode(VOID) +{ + NTSTATUS Status; + UINT ErrMode; + + /* Query the current setting */ + Status = NtQueryInformationProcess(NtCurrentProcess(), + ProcessDefaultHardErrorMode, + (PVOID)&ErrMode, + sizeof(ErrMode), + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail if we couldn't query */ + BaseSetLastNTError(Status); + return 0; + } + + /* Check if NOT failing critical errors was requested */ + if (ErrMode & SEM_FAILCRITICALERRORS) + { + /* Mask it out, since the native API works differently */ + ErrMode &= ~SEM_FAILCRITICALERRORS; + } + else + { + /* OR it if the caller didn't, due to different native semantics */ + ErrMode |= SEM_FAILCRITICALERRORS; + } + + /* Return the mode */ + return ErrMode; +} + /* * @implemented */ @@ -309,7 +261,7 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo) &DebugPort, sizeof(HANDLE), NULL); if (!NT_SUCCESS(ErrCode) && ErrCode != STATUS_NOT_IMPLEMENTED) { - SetLastErrorByStatus(ErrCode); + BaseSetLastNTError(ErrCode); return EXCEPTION_EXECUTE_HANDLER; } @@ -435,4 +387,308 @@ RaiseException(IN DWORD dwExceptionCode, RtlRaiseException(&ExceptionRecord); } +/* + * @implemented + */ +UINT +WINAPI +SetErrorMode(IN UINT uMode) +{ + UINT PrevErrMode, NewMode; + NTSTATUS Status; + + /* Get the previous mode */ + PrevErrMode = GetErrorMode(); + NewMode = uMode; + + /* Check if failing critical errors was requested */ + if (NewMode & SEM_FAILCRITICALERRORS) + { + /* Mask it out, since the native API works differently */ + NewMode &= ~SEM_FAILCRITICALERRORS; + } + else + { + /* OR it if the caller didn't, due to different native semantics */ + NewMode |= SEM_FAILCRITICALERRORS; + } + + /* Set the new mode */ + Status = NtSetInformationProcess(NtCurrentProcess(), + ProcessDefaultHardErrorMode, + (PVOID)&NewMode, + sizeof(NewMode)); + if(!NT_SUCCESS(Status)) BaseSetLastNTError(Status); + + /* Return the previous mode */ + return PrevErrMode; +} + +/* + * @implemented + */ +LPTOP_LEVEL_EXCEPTION_FILTER +WINAPI +SetUnhandledExceptionFilter( + IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) +{ + return InterlockedExchangePointer(&GlobalTopLevelExceptionFilter, + lpTopLevelExceptionFilter); +} + +/* + * @implemented + */ +BOOL +WINAPI +IsBadReadPtr(IN LPCVOID lp, + IN UINT_PTR ucb) +{ + ULONG PageSize; + BOOLEAN Result = FALSE; + volatile CHAR *Current; + PCHAR Last; + + /* Quick cases */ + if (!ucb) return FALSE; + if (!lp) return TRUE; + + /* Get the page size */ + PageSize = BaseStaticServerData->SysInfo.PageSize; + + /* Calculate the last page */ + Last = (PCHAR)((ULONG_PTR)lp + ucb - 1); + + /* Another quick failure case */ + if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE; + + /* Enter SEH */ + _SEH2_TRY + { + /* Probe the entire range */ + Current = (volatile CHAR*)lp; + Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); + do + { + *Current; + Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE); + } while (Current <= Last); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* We hit an exception, so return true */ + Result = TRUE; + } + _SEH2_END + + /* Return exception status */ + return Result; +} + +/* + * @implemented + */ +BOOL +NTAPI +IsBadHugeReadPtr(LPCVOID lp, + UINT_PTR ucb) +{ + /* Implementation is the same on 32-bit */ + return IsBadReadPtr(lp, ucb); +} + +/* + * @implemented + */ +BOOL +NTAPI +IsBadCodePtr(FARPROC lpfn) +{ + /* Executing has the same privileges as reading */ + return IsBadReadPtr((LPVOID)lpfn, 1); +} + +/* + * @implemented + */ +BOOL +NTAPI +IsBadWritePtr(LPVOID lp, + UINT_PTR ucb) +{ + ULONG PageSize; + BOOLEAN Result = FALSE; + volatile CHAR *Current; + PCHAR Last; + + /* Quick cases */ + if (!ucb) return FALSE; + if (!lp) return TRUE; + + /* Get the page size */ + PageSize = BaseStaticServerData->SysInfo.PageSize; + + /* Calculate the last page */ + Last = (PCHAR)((ULONG_PTR)lp + ucb - 1); + + /* Another quick failure case */ + if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE; + + /* Enter SEH */ + _SEH2_TRY + { + /* Probe the entire range */ + Current = (volatile CHAR*)lp; + Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); + do + { + *Current = *Current; + Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE); + } while (Current <= Last); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* We hit an exception, so return true */ + Result = TRUE; + } + _SEH2_END + + /* Return exception status */ + return Result; +} + +/* + * @implemented + */ +BOOL +NTAPI +IsBadHugeWritePtr(LPVOID lp, + UINT_PTR ucb) +{ + /* Implementation is the same on 32-bit */ + return IsBadWritePtr(lp, ucb); +} + +/* + * @implemented + */ +BOOL +NTAPI +IsBadStringPtrW(IN LPCWSTR lpsz, + UINT_PTR ucchMax) +{ + BOOLEAN Result = FALSE; + volatile WCHAR *Current; + PWCHAR Last; + WCHAR Char; + + /* Quick cases */ + if (!ucchMax) return FALSE; + if (!lpsz) return TRUE; + + /* Calculate the last page */ + Last = (PWCHAR)((ULONG_PTR)lpsz + (ucchMax * 2) - 2); + + /* Enter SEH */ + _SEH2_TRY + { + /* Probe the entire range */ + Current = (volatile WCHAR*)lpsz; + Last = (PWCHAR)(PAGE_ROUND_DOWN(Last)); + do + { + Char = *Current; + Current++; + } while (Char && (Current != Last + 1)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* We hit an exception, so return true */ + Result = TRUE; + } + _SEH2_END + + /* Return exception status */ + return Result; +} + +/* + * @implemented + */ +BOOL +NTAPI +IsBadStringPtrA(IN LPCSTR lpsz, + UINT_PTR ucchMax) +{ + BOOLEAN Result = FALSE; + volatile CHAR *Current; + PCHAR Last; + CHAR Char; + + /* Quick cases */ + if (!ucchMax) return FALSE; + if (!lpsz) return TRUE; + + /* Calculate the last page */ + Last = (PCHAR)((ULONG_PTR)lpsz + ucchMax - 1); + + /* Enter SEH */ + _SEH2_TRY + { + /* Probe the entire range */ + Current = (volatile CHAR*)lpsz; + Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); + do + { + Char = *Current; + Current++; + } while (Char && (Current != Last + 1)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* We hit an exception, so return true */ + Result = TRUE; + } + _SEH2_END + + /* Return exception status */ + return Result; +} + +/* + * @implemented + */ +VOID +WINAPI +SetLastError(IN DWORD dwErrCode) +{ + /* Break if a debugger requested checking for this error code */ + if ((g_dwLastErrorToBreakOn) && (g_dwLastErrorToBreakOn == dwErrCode)) DbgBreakPoint(); + + /* Set last error if it's a new error */ + if (NtCurrentTeb()->LastErrorValue != dwErrCode) NtCurrentTeb()->LastErrorValue = dwErrCode; +} + +/* + * @implemented + */ +VOID +WINAPI +BaseSetLastNTError(IN NTSTATUS Status) +{ + /* Convert from NT to Win32, then set */ + SetLastError(RtlNtStatusToDosError(Status)); +} + +/* + * @implemented + */ +DWORD +WINAPI +GetLastError(VOID) +{ + /* Return the current value */ + return NtCurrentTeb()->LastErrorValue; +} + /* EOF */ diff --git a/dll/win32/kernel32/thread/fiber.c b/dll/win32/kernel32/client/fiber.c similarity index 50% rename from dll/win32/kernel32/thread/fiber.c rename to dll/win32/kernel32/client/fiber.c index e815d0b7b90..101ca1621f8 100644 --- a/dll/win32/kernel32/thread/fiber.c +++ b/dll/win32/kernel32/client/fiber.c @@ -26,6 +26,18 @@ typedef struct _FIBER /* Field offsets: */ PVOID ActivationContextStack; /* 0x2E8 */ } FIBER, *PFIBER; +/* PRIVATE FUNCTIONS **********************************************************/ + +VOID +WINAPI +BaseRundownFls(IN PVOID FlsData) +{ + /* No FLS support yet */ + +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + /* * @implemented */ @@ -33,24 +45,27 @@ BOOL WINAPI ConvertFiberToThread(VOID) { - PTEB pTeb = NtCurrentTeb(); + PTEB Teb; + PFIBER FiberData; DPRINT1("Converting Fiber to Thread\n"); - /* the current thread isn't running a fiber: failure */ - if (!pTeb->HasFiberData) + /* Check if the thread is already not a fiber */ + Teb = NtCurrentTeb(); + if (!Teb->HasFiberData) { - SetLastError(ERROR_INVALID_PARAMETER); + /* Fail */ + SetLastError(ERROR_ALREADY_THREAD); return FALSE; } /* this thread won't run a fiber anymore */ - pTeb->HasFiberData = FALSE; + Teb->HasFiberData = FALSE; + FiberData = Teb->NtTib.FiberData; + Teb->NtTib.FiberData = NULL; - /* free the fiber */ - if(pTeb->NtTib.FiberData != NULL) - { - RtlFreeHeap(GetProcessHeap(), 0, pTeb->NtTib.FiberData); - } + /* Free the fiber */ + ASSERT(FiberData != NULL); + RtlFreeHeap(GetProcessHeap(), 0, FiberData); /* success */ return TRUE; @@ -143,73 +158,83 @@ CreateFiberEx(SIZE_T dwStackCommitSize, LPFIBER_START_ROUTINE lpStartAddress, LPVOID lpParameter) { - PFIBER pfCurFiber; - NTSTATUS nErrCode; - INITIAL_TEB usFiberInitialTeb; + PFIBER Fiber; + NTSTATUS Status; + INITIAL_TEB InitialTeb; PVOID ActivationContextStack = NULL; DPRINT("Creating Fiber\n"); -#ifdef SXS_SUPPORT_ENABLED + /* Check for invalid flags */ + if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + /* Allocate the Activation Context Stack */ - nErrCode = RtlAllocateActivationContextStack(&ActivationContextStack); -#endif + Status = RtlAllocateActivationContextStack(&ActivationContextStack); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return NULL; + } /* Allocate the fiber */ - pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(), - 0, - sizeof(FIBER)); - /* Failure */ - if (pfCurFiber == NULL) + Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER)); + if (!Fiber) { + /* Fail */ SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } /* Create the stack for the fiber */ - nErrCode = BasepCreateStack(NtCurrentProcess(), - dwStackCommitSize, - dwStackReserveSize, - &usFiberInitialTeb); - /* Failure */ - if(!NT_SUCCESS(nErrCode)) + Status = BasepCreateStack(NtCurrentProcess(), + dwStackCommitSize, + dwStackReserveSize, + &InitialTeb); + if (!NT_SUCCESS(Status)) { /* Free the fiber */ - RtlFreeHeap(GetProcessHeap(), 0, pfCurFiber); + RtlFreeHeap(GetProcessHeap(), 0, Fiber); + + /* Free the activation context */ + DPRINT1("Leaking activation stack because nobody implemented free"); + //RtlFreeActivationContextStack(&ActivationContextStack); /* Failure */ - SetLastErrorByStatus(nErrCode); + BaseSetLastNTError(Status); return NULL; } /* Clear the context */ - RtlZeroMemory(&pfCurFiber->Context, sizeof(CONTEXT)); - - /* copy the data into the fiber */ - pfCurFiber->StackBase = usFiberInitialTeb.StackBase; - pfCurFiber->StackLimit = usFiberInitialTeb.StackLimit; - pfCurFiber->DeallocationStack = usFiberInitialTeb.AllocatedStackBase; - pfCurFiber->Parameter = lpParameter; - pfCurFiber->ExceptionList = (struct _EXCEPTION_REGISTRATION_RECORD *)-1; - pfCurFiber->GuaranteedStackBytes = 0; - pfCurFiber->FlsData = NULL; - pfCurFiber->ActivationContextStack = ActivationContextStack; - pfCurFiber->Context.ContextFlags = CONTEXT_FULL; - - /* Save FPU State if requsted */ - if (dwFlags & FIBER_FLAG_FLOAT_SWITCH) - { - pfCurFiber->Context.ContextFlags |= CONTEXT_FLOATING_POINT; - } + RtlZeroMemory(&Fiber->Context, sizeof(CONTEXT)); + + /* Copy the data into the fiber */ + Fiber->StackBase = InitialTeb.StackBase; + Fiber->StackLimit = InitialTeb.StackLimit; + Fiber->DeallocationStack = InitialTeb.AllocatedStackBase; + Fiber->Parameter = lpParameter; + Fiber->ExceptionList = EXCEPTION_CHAIN_END; + Fiber->GuaranteedStackBytes = 0; + Fiber->FlsData = NULL; + Fiber->ActivationContextStack = ActivationContextStack; + Fiber->Context.ContextFlags = CONTEXT_FULL; + + /* Save FPU State if requested */ + Fiber->Context.ContextFlags = (dwFlags & FIBER_FLAG_FLOAT_SWITCH) ? CONTEXT_FLOATING_POINT : 0; /* initialize the context for the fiber */ - BasepInitializeContext(&pfCurFiber->Context, + BasepInitializeContext(&Fiber->Context, lpParameter, lpStartAddress, - usFiberInitialTeb.StackBase, + InitialTeb.StackBase, 2); - /* Return the Fiber */ - return pfCurFiber; + /* Return the Fiber */ + return Fiber; } /* @@ -219,20 +244,29 @@ VOID WINAPI DeleteFiber(LPVOID lpFiber) { - SIZE_T nSize = 0; - PVOID pStackAllocBase = ((PFIBER)lpFiber)->DeallocationStack; + SIZE_T Size = 0; + PFIBER Fiber = (PFIBER)lpFiber; + PTEB Teb; - /* free the fiber */ - RtlFreeHeap(GetProcessHeap(), 0, lpFiber); + /* First, exit the thread */ + Teb = NtCurrentTeb(); + if ((Teb->HasFiberData) && (Teb->NtTib.FiberData == Fiber)) ExitThread(1); - /* the fiber is deleting itself: let the system deallocate the stack */ - if(NtCurrentTeb()->NtTib.FiberData == lpFiber) ExitThread(1); - - /* deallocate the stack */ + /* Now de-allocate the stack */ NtFreeVirtualMemory(NtCurrentProcess(), - &pStackAllocBase, - &nSize, + &Fiber->DeallocationStack, + &Size, MEM_RELEASE); + + /* Get rid of FLS */ + if (Fiber->FlsData) BaseRundownFls(Fiber->FlsData); + + /* Get rid of the activation stack */ + DPRINT1("Leaking activation stack because nobody implemented free"); + //RtlFreeActivationContextStack(Fiber->ActivationContextStack); + + /* Free the fiber data */ + RtlFreeHeap(GetProcessHeap(), 0, lpFiber); } /* @@ -245,31 +279,108 @@ IsThreadAFiber(VOID) return NtCurrentTeb()->HasFiberData; } +/* + * @unimplemented + */ +DWORD +WINAPI +FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) +{ + (void)lpCallback; -__declspec(noreturn) -VOID + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FLS_OUT_OF_INDEXES; +} + + +/* + * @unimplemented + */ +BOOL WINAPI -BaseFiberStartup(VOID) +FlsFree(DWORD dwFlsIndex) { -#ifdef _M_IX86 - PFIBER Fiber = GetCurrentFiber(); - - /* Call the Thread Startup Routine */ - DPRINT("Starting Fiber\n"); - BaseThreadStartup((LPTHREAD_START_ROUTINE)Fiber->Context.Eax, - (LPVOID)Fiber->Context.Ebx); -#elif defined(_M_AMD64) - PFIBER Fiber = GetFiberData(); - - /* Call the Thread Startup Routine */ - DPRINT1("Starting Fiber\n"); - BaseThreadStartup((LPTHREAD_START_ROUTINE)Fiber->Context.Rax, - (LPVOID)Fiber->Context.Rbx); -#else -#warning Unknown architecture + (void)dwFlsIndex; + UNIMPLEMENTED; - DbgBreakPoint(); -#endif + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @implemented + */ +PVOID +WINAPI +FlsGetValue(DWORD dwFlsIndex) +{ + PVOID *ppFlsSlots; + PVOID pRetVal; + + if(dwFlsIndex >= 128) goto l_InvalidParam; + + ppFlsSlots = NtCurrentTeb()->FlsData; + + if(ppFlsSlots == NULL) goto l_InvalidParam; + + SetLastError(0); + pRetVal = ppFlsSlots[dwFlsIndex + 2]; + + return pRetVal; + +l_InvalidParam: + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; +} + + +/* + * @implemented + */ +BOOL +WINAPI +FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData) +{ + PVOID *ppFlsSlots; + TEB *pTeb = NtCurrentTeb(); + + if(dwFlsIndex >= 128) goto l_InvalidParam; + + ppFlsSlots = pTeb->FlsData; + + if (ppFlsSlots == NULL) + { + PEB *pPeb = pTeb->ProcessEnvironmentBlock; + + ppFlsSlots = RtlAllocateHeap(pPeb->ProcessHeap, + HEAP_ZERO_MEMORY, + (128 + 2) * sizeof(PVOID)); + if(ppFlsSlots == NULL) goto l_OutOfMemory; + + pTeb->FlsData = ppFlsSlots; + + RtlAcquirePebLock(); + + /* TODO: initialization */ + + RtlReleasePebLock(); + } + + ppFlsSlots[dwFlsIndex + 2] = lpFlsData; + + return TRUE; + +l_OutOfMemory: + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto l_Fail; + +l_InvalidParam: + SetLastError(ERROR_INVALID_PARAMETER); + +l_Fail: + return FALSE; } /* EOF */ diff --git a/dll/win32/kernel32/client/file/backup.c b/dll/win32/kernel32/client/file/backup.c new file mode 100644 index 00000000000..24c2a751233 --- /dev/null +++ b/dll/win32/kernel32/client/file/backup.c @@ -0,0 +1,80 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/backup.c + * PURPOSE: Backup functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +/* + * @unimplemented + */ +BOOL +WINAPI +BackupRead ( + HANDLE hFile, + LPBYTE lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + BOOL bAbort, + BOOL bProcessSecurity, + LPVOID * lpContext + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +BackupSeek ( + HANDLE hFile, + DWORD dwLowBytesToSeek, + DWORD dwHighBytesToSeek, + LPDWORD lpdwLowByteSeeked, + LPDWORD lpdwHighByteSeeked, + LPVOID * lpContext + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +BackupWrite ( + HANDLE hFile, + LPBYTE lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + BOOL bAbort, + BOOL bProcessSecurity, + LPVOID * lpContext + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/bintype.c b/dll/win32/kernel32/client/file/bintype.c new file mode 100644 index 00000000000..824121c395c --- /dev/null +++ b/dll/win32/kernel32/client/file/bintype.c @@ -0,0 +1,343 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/bintype.c + * PURPOSE: Binary detection functions + * PROGRAMMER: Alexandre Julliard (WINE) + * Thomas Weidenmueller (w3seek@users.sourceforge.net) + * UPDATE HISTORY: + * 02/05/2004 - Ported/Adapted from WINE + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +#if DBG +DEBUG_CHANNEL(kernel32file); +#endif + +/* FUNCTIONS ****************************************************************/ + +/* Check whether a file is an OS/2 or a very old Windows executable + * by testing on import of KERNEL. + * + * FIXME: is reading the module imports the only way of discerning + * old Windows binaries from OS/2 ones ? At least it seems so... + */ +static DWORD WINAPI +InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne) +{ + DWORD CurPos; + LPWORD modtab = NULL; + LPSTR nametab = NULL; + DWORD Read, Ret; + int i; + + Ret = BINARY_OS216; + CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + + /* read modref table */ + if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_modtab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) || + (!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) || + (!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) || + (Read != (DWORD)ne->ne_cmod * sizeof(WORD))) + { + goto broken; + } + + /* read imported names table */ + if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_imptab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) || + (!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) || + (!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) || + (Read != (DWORD)ne->ne_enttab - ne->ne_imptab)) + { + goto broken; + } + + for(i = 0; i < ne->ne_cmod; i++) + { + LPSTR module; + module = &nametab[modtab[i]]; + if(!strncmp(&module[1], "KERNEL", module[0])) + { + /* very old windows file */ + Ret = BINARY_WIN16; + goto done; + } + } + + broken: + WARN("InternalIsOS2OrOldWin(): Binary file seems to be broken\n"); + + done: + HeapFree(GetProcessHeap(), 0, modtab); + HeapFree(GetProcessHeap(), 0, nametab); + SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN); + return Ret; +} + +static DWORD WINAPI +InternalGetBinaryType(HANDLE hFile) +{ + union + { + struct + { + unsigned char magic[4]; + unsigned char ignored[12]; + unsigned short type; + } elf; + struct + { + unsigned long magic; + unsigned long cputype; + unsigned long cpusubtype; + unsigned long filetype; + } macho; + IMAGE_DOS_HEADER mz; + } Header; + char magic[4]; + DWORD Read; + + if((SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) || + (!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) || + (Read != sizeof(Header)))) + { + return BINARY_UNKNOWN; + } + + if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic))) + { + /* FIXME: we don't bother to check byte order, architecture, etc. */ + switch(Header.elf.type) + { + case 2: + return BINARY_UNIX_EXE; + case 3: + return BINARY_UNIX_LIB; + } + return BINARY_UNKNOWN; + } + + /* Mach-o File with Endian set to Big Endian or Little Endian*/ + if(Header.macho.magic == 0xFEEDFACE || + Header.macho.magic == 0xCEFAEDFE) + { + switch(Header.macho.filetype) + { + case 0x8: + /* MH_BUNDLE */ + return BINARY_UNIX_LIB; + } + return BINARY_UNKNOWN; + } + + /* Not ELF, try DOS */ + if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE) + { + /* We do have a DOS image so we will now try to seek into + * the file by the amount indicated by the field + * "Offset to extended header" and read in the + * "magic" field information at that location. + * This will tell us if there is more header information + * to read or not. + */ + if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) || + (!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) || + (Read != sizeof(magic)))) + { + return BINARY_DOS; + } + + /* Reading the magic field succeeded so + * we will try to determine what type it is. + */ + if(!memcmp(magic, "PE\0\0", sizeof(magic))) + { + IMAGE_FILE_HEADER FileHeader; + if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) || + (Read != sizeof(IMAGE_FILE_HEADER))) + { + return BINARY_DOS; + } + + /* FIXME - detect 32/64 bit */ + + if(FileHeader.Characteristics & IMAGE_FILE_DLL) + return BINARY_PE_DLL32; + return BINARY_PE_EXE32; + } + + if(!memcmp(magic, "NE", 1)) + { + /* This is a Windows executable (NE) header. This can + * mean either a 16-bit OS/2 or a 16-bit Windows or even a + * DOS program (running under a DOS extender). To decide + * which, we'll have to read the NE header. + */ + IMAGE_OS2_HEADER ne; + if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) || + !ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) || + (Read != sizeof(IMAGE_OS2_HEADER))) + { + /* Couldn't read header, so abort. */ + return BINARY_DOS; + } + + switch(ne.ne_exetyp) + { + case 2: + return BINARY_WIN16; + case 5: + return BINARY_DOS; + default: + return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne); + } + } + return BINARY_DOS; + } + return BINARY_UNKNOWN; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetBinaryTypeW ( + LPCWSTR lpApplicationName, + LPDWORD lpBinaryType + ) +{ + HANDLE hFile; + DWORD BinType; + + if(!lpApplicationName || !lpBinaryType) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, 0); + if(hFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + BinType = InternalGetBinaryType(hFile); + CloseHandle(hFile); + + switch(BinType) + { + case BINARY_UNKNOWN: + { + WCHAR *dot; + + /* + * guess from filename + */ + if(!(dot = wcsrchr(lpApplicationName, L'.'))) + { + return FALSE; + } + if(!lstrcmpiW(dot, L".COM")) + { + *lpBinaryType = SCS_DOS_BINARY; + return TRUE; + } + if(!lstrcmpiW(dot, L".PIF")) + { + *lpBinaryType = SCS_PIF_BINARY; + return TRUE; + } + return FALSE; + } + case BINARY_PE_EXE32: + case BINARY_PE_DLL32: + { + *lpBinaryType = SCS_32BIT_BINARY; + return TRUE; + } + case BINARY_PE_EXE64: + case BINARY_PE_DLL64: + { + *lpBinaryType = SCS_64BIT_BINARY; + return TRUE; + } + case BINARY_WIN16: + { + *lpBinaryType = SCS_WOW_BINARY; + return TRUE; + } + case BINARY_OS216: + { + *lpBinaryType = SCS_OS216_BINARY; + return TRUE; + } + case BINARY_DOS: + { + *lpBinaryType = SCS_DOS_BINARY; + return TRUE; + } + case BINARY_UNIX_EXE: + case BINARY_UNIX_LIB: + { + return FALSE; + } + } + + ERR("Invalid binary type returned!\n", BinType); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetBinaryTypeA(IN LPCSTR lpApplicationName, + OUT LPDWORD lpBinaryType) +{ + ANSI_STRING ApplicationNameString; + UNICODE_STRING ApplicationNameW; + BOOL StringAllocated = FALSE, Result; + NTSTATUS Status; + + RtlInitAnsiString(&ApplicationNameString, lpApplicationName); + + if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength) + { + StringAllocated = TRUE; + Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE); + } + else + { + Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE); + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if (StringAllocated) + { + Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType); + RtlFreeUnicodeString(&ApplicationNameW); + } + else + { + Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType); + } + + return Result; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/cnotify.c b/dll/win32/kernel32/client/file/cnotify.c new file mode 100644 index 00000000000..120be594435 --- /dev/null +++ b/dll/win32/kernel32/client/file/cnotify.c @@ -0,0 +1,255 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +BOOL WINAPI +FindCloseChangeNotification (HANDLE hChangeHandle) +{ + NTSTATUS Status = NtClose(hChangeHandle); + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +FindFirstChangeNotificationA(IN LPCSTR lpPathName, + IN BOOL bWatchSubtree, + IN DWORD dwNotifyFilter) +{ + /* Call the W(ide) function */ + ConvertWin32AnsiChangeApiToUnicodeApi(FindFirstChangeNotification, + lpPathName, + bWatchSubtree, + dwNotifyFilter); +} + + +/* + * @implemented + */ +HANDLE +WINAPI +FindFirstChangeNotificationW ( + LPCWSTR lpPathName, + BOOL bWatchSubtree, + DWORD dwNotifyFilter + ) +{ + NTSTATUS Status; + UNICODE_STRING NtPathU; + IO_STATUS_BLOCK IoStatus; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hDir; + + if (!RtlDosPathNameToNtPathName_U (lpPathName, + &NtPathU, + NULL, + NULL)) + { + BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); + return INVALID_HANDLE_VALUE; + } + + + + InitializeObjectAttributes (&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile (&hDir, + SYNCHRONIZE|FILE_LIST_DIRECTORY, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtPathU.Buffer); + + + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + Status = NtNotifyChangeDirectoryFile(hDir, + NULL, + NULL, + NULL, + &IoStatus, + NULL,//Buffer, + 0,//BufferLength, + dwNotifyFilter, + (BOOLEAN)bWatchSubtree); + if (!NT_SUCCESS(Status)) + { + NtClose(hDir); + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + return hDir; +} + + +/* + * @implemented + */ +BOOL +WINAPI +FindNextChangeNotification ( + HANDLE hChangeHandle + ) +{ + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + Status = NtNotifyChangeDirectoryFile(hChangeHandle, + NULL, + NULL, + NULL, + &IoStatus, + NULL,//Buffer, + 0,//BufferLength, + FILE_NOTIFY_CHANGE_SECURITY,//meaningless/ignored for subsequent calls, but must contain a valid flag + 0 //meaningless/ignored for subsequent calls + ); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +extern VOID +(WINAPI ApcRoutine)(PVOID ApcContext, + struct _IO_STATUS_BLOCK* IoStatusBlock, + ULONG Reserved); + + +/* + * @implemented + */ +BOOL +WINAPI +ReadDirectoryChangesW( + HANDLE hDirectory, + LPVOID lpBuffer OPTIONAL, + DWORD nBufferLength, + BOOL bWatchSubtree, + DWORD dwNotifyFilter, + LPDWORD lpBytesReturned, /* undefined for asych. operations */ + LPOVERLAPPED lpOverlapped OPTIONAL, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine /* OPTIONAL???????? */ + ) +{ + PVOID CompletionRoutine; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + HANDLE EventHandle; + PIO_APC_ROUTINE IoApcRoutine; + + if (lpOverlapped ) + { + if (lpCompletionRoutine) + { + CompletionRoutine = (PVOID) lpCompletionRoutine; + EventHandle = NULL; + IoApcRoutine = ApcRoutine; + } + else + { + if (((ULONG_PTR) lpOverlapped->hEvent & 1) == 0) + CompletionRoutine = (PVOID) lpOverlapped; + else + CompletionRoutine = NULL; + + EventHandle = lpOverlapped->hEvent; + IoApcRoutine = NULL; + } + + lpOverlapped->Internal = STATUS_PENDING; + } + else + { + EventHandle = NULL; + IoApcRoutine = NULL; + CompletionRoutine = NULL; + } + + Status = NtNotifyChangeDirectoryFile( + hDirectory, + EventHandle, + IoApcRoutine, + CompletionRoutine, /* ApcContext */ + lpOverlapped ? (PIO_STATUS_BLOCK) lpOverlapped : &IoStatus, + lpBuffer, + nBufferLength, + dwNotifyFilter, + (BOOLEAN)bWatchSubtree + ); + + if ((Status == STATUS_PENDING) && (!lpOverlapped)) + { + Status = NtWaitForSingleObject(hDirectory, FALSE, NULL); + + if (NT_SUCCESS(Status)) + { + Status = IoStatus.Status; + } + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + + /* NOTE: lpBytesReturned is undefined for asynch. operations */ + *lpBytesReturned = IoStatus.Information; + + return TRUE; +} + + + + + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/console.c b/dll/win32/kernel32/client/file/console.c new file mode 100644 index 00000000000..52333f6731e --- /dev/null +++ b/dll/win32/kernel32/client/file/console.c @@ -0,0 +1,4337 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/console.c + * PURPOSE: Win32 server console functions + * PROGRAMMER: James Tabor + * + * UPDATE HISTORY: + * 199901?? ?? Created + * 19990204 EA SetConsoleTitleA + * 19990306 EA Stubs + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +extern RTL_CRITICAL_SECTION ConsoleLock; +extern BOOL ConsoleInitialized; +extern BOOL WINAPI IsDebuggerPresent(VOID); + +/* GLOBALS *******************************************************************/ + +PHANDLER_ROUTINE InitialHandler[1]; +PHANDLER_ROUTINE* CtrlHandlers; +ULONG NrCtrlHandlers; +ULONG NrAllocatedHandlers; + +#define INPUTEXENAME_BUFLEN 256 +static WCHAR InputExeName[INPUTEXENAME_BUFLEN] = L""; + +/* Default Console Control Handler *******************************************/ + +BOOL +WINAPI +DefaultConsoleCtrlHandler(DWORD Event) +{ + DPRINT("Default handler called: %lx\n", Event); + switch(Event) + { + case CTRL_C_EVENT: + DPRINT("Ctrl-C Event\n"); + break; + + case CTRL_BREAK_EVENT: + DPRINT("Ctrl-Break Event\n"); + break; + + case CTRL_SHUTDOWN_EVENT: + DPRINT("Ctrl Shutdown Event\n"); + break; + + case CTRL_CLOSE_EVENT: + DPRINT("Ctrl Close Event\n"); + break; + + case CTRL_LOGOFF_EVENT: + DPRINT("Ctrl Logoff Event\n"); + break; + } + + ExitProcess(CONTROL_C_EXIT); + return TRUE; +} + +__declspec(noreturn) +VOID +CALLBACK +ConsoleControlDispatcher(DWORD CodeAndFlag) +{ + DWORD nExitCode = 0; + DWORD nCode = CodeAndFlag & MAXLONG; + UINT i; + EXCEPTION_RECORD erException; + + DPRINT("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + switch(nCode) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + { + if (IsDebuggerPresent()) + { + erException.ExceptionCode = (nCode == CTRL_C_EVENT ? + DBG_CONTROL_C : DBG_CONTROL_BREAK); + erException.ExceptionFlags = 0; + erException.ExceptionRecord = NULL; + erException.ExceptionAddress = DefaultConsoleCtrlHandler; + erException.NumberParameters = 0; + + _SEH2_TRY + { + RtlRaiseException(&erException); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + RtlEnterCriticalSection(&ConsoleLock); + + if ((nCode != CTRL_C_EVENT) || + (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1)) + { + for (i = NrCtrlHandlers; i > 0; i--) + { + if (CtrlHandlers[i - 1](nCode)) break; + } + } + + RtlLeaveCriticalSection(&ConsoleLock); + } + _SEH2_END; + + ExitThread(0); + } + + break; + } + + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + break; + + case 3: + + ExitThread(0); + break; + + case 4: + + ExitProcess(CONTROL_C_EXIT); + break; + + default: + + ASSERT(FALSE); + break; + } + + ASSERT(ConsoleInitialized); + + RtlEnterCriticalSection(&ConsoleLock); + nExitCode = 0; + if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1)) + { + for (i = NrCtrlHandlers; i > 0; i--) + { + if ((i == 1) && + (CodeAndFlag & MINLONG) && + ((nCode == CTRL_LOGOFF_EVENT) || (nCode == CTRL_SHUTDOWN_EVENT))) + { + DPRINT("Skipping system/service apps\n"); + break; + } + + if (CtrlHandlers[i - 1](nCode)) + { + switch(nCode) + { + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + case 3: + nExitCode = CodeAndFlag; + break; + } + break; + } + } + } + + RtlLeaveCriticalSection(&ConsoleLock); + ExitThread(nExitCode); +} + +/* Get the size needed to copy a string to a capture buffer, including alignment */ +static ULONG +IntStringSize(LPCVOID String, + BOOL Unicode) +{ + ULONG Size = (Unicode ? wcslen(String) : strlen(String)) * sizeof(WCHAR); + return (Size + 3) & -4; +} + +/* Copy a string to a capture buffer */ +static VOID +IntCaptureMessageString(PCSR_CAPTURE_BUFFER CaptureBuffer, + LPCVOID String, + BOOL Unicode, + PUNICODE_STRING RequestString) +{ + ULONG Size; + if (Unicode) + { + Size = wcslen(String) * sizeof(WCHAR); + CsrCaptureMessageBuffer(CaptureBuffer, (PVOID)String, Size, (PVOID *)&RequestString->Buffer); + } + else + { + Size = strlen(String); + CsrAllocateMessagePointer(CaptureBuffer, Size * sizeof(WCHAR), (PVOID *)&RequestString->Buffer); + Size = MultiByteToWideChar(CP_ACP, 0, String, Size, RequestString->Buffer, Size * sizeof(WCHAR)) + * sizeof(WCHAR); + } + RequestString->Length = RequestString->MaximumLength = Size; +} + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +AddConsoleAliasA(LPCSTR lpSource, + LPCSTR lpTarget, + LPCSTR lpExeName) +{ + LPWSTR lpSourceW = NULL; + LPWSTR lpTargetW = NULL; + LPWSTR lpExeNameW = NULL; + BOOL bRetVal; + + if (lpSource) + BasepAnsiStringToHeapUnicodeString(lpSource, (LPWSTR*) &lpSourceW); + if (lpTarget) + BasepAnsiStringToHeapUnicodeString(lpTarget, (LPWSTR*) &lpTargetW); + if (lpExeName) + BasepAnsiStringToHeapUnicodeString(lpExeName, (LPWSTR*) &lpExeNameW); + + bRetVal = AddConsoleAliasW(lpSourceW, lpTargetW, lpExeNameW); + + /* Clean up */ + if (lpSourceW) + RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpSourceW); + if (lpTargetW) + RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpTargetW); + if (lpExeNameW) + RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpExeNameW); + + return bRetVal; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +AddConsoleAliasW(LPCWSTR lpSource, + LPCWSTR lpTarget, + LPCWSTR lpExeName) +{ + PCSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + ULONG SourceLength; + ULONG TargetLength = 0; + ULONG ExeLength; + ULONG Size; + ULONG RequestLength; + WCHAR * Ptr; + + DPRINT("AddConsoleAliasW enterd with lpSource %S lpTarget %S lpExeName %S\n", lpSource, lpTarget, lpExeName); + + ExeLength = wcslen(lpExeName) + 1; + SourceLength = wcslen(lpSource)+ 1; + if (lpTarget) + TargetLength = wcslen(lpTarget) + 1; + + Size = (ExeLength + SourceLength + TargetLength) * sizeof(WCHAR); + RequestLength = sizeof(CSR_API_MESSAGE) + Size; + + Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, RequestLength); + Ptr = (WCHAR*)(((ULONG_PTR)Request) + sizeof(CSR_API_MESSAGE)); + + wcscpy(Ptr, lpSource); + Request->Data.AddConsoleAlias.SourceLength = SourceLength; + Ptr = (WCHAR*)(((ULONG_PTR)Request) + sizeof(CSR_API_MESSAGE) + SourceLength * sizeof(WCHAR)); + + wcscpy(Ptr, lpExeName); + Request->Data.AddConsoleAlias.ExeLength = ExeLength; + Ptr = (WCHAR*)(((ULONG_PTR)Request) + sizeof(CSR_API_MESSAGE) + (ExeLength + SourceLength)* sizeof(WCHAR)); + + if (lpTarget) /* target can be optional */ + wcscpy(Ptr, lpTarget); + + Request->Data.AddConsoleAlias.TargetLength = TargetLength; + + CsrRequest = MAKE_CSR_API(ADD_CONSOLE_ALIAS, CSR_CONSOLE); + Status = CsrClientCallServer(Request, + NULL, + CsrRequest, + RequestLength); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status)) + { + BaseSetLastNTError(Status); + RtlFreeHeap(GetProcessHeap(), 0, Request); + return FALSE; + } + + RtlFreeHeap(GetProcessHeap(), 0, Request); + return TRUE; +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +ConsoleMenuControl(HANDLE hConsole, + DWORD Unknown1, + DWORD Unknown2) +{ + DPRINT1("ConsoleMenuControl(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", hConsole, Unknown1, Unknown2); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +DuplicateConsoleHandle(HANDLE hConsole, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + if (dwOptions & ~(DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS) + || (!(dwOptions & DUPLICATE_SAME_ACCESS) + && dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE))) + { + SetLastError (ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + CsrRequest = MAKE_CSR_API(DUPLICATE_HANDLE, CSR_NATIVE); + Request.Data.DuplicateHandleRequest.Handle = hConsole; + Request.Data.DuplicateHandleRequest.Access = dwDesiredAccess; + Request.Data.DuplicateHandleRequest.Inheritable = bInheritHandle; + Request.Data.DuplicateHandleRequest.Options = dwOptions; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status=Request.Status)) + { + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + return Request.Data.DuplicateHandleRequest.Handle; +} + + +static BOOL +IntExpungeConsoleCommandHistory(LPCVOID lpExeName, BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(EXPUNGE_COMMAND_HISTORY, CSR_CONSOLE); + NTSTATUS Status; + + if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + &Request.Data.ExpungeCommandHistory.ExeName); + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + CsrFreeCaptureBuffer(CaptureBuffer); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + return TRUE; +} + +/* + * @implemented (Undocumented) + */ +BOOL +WINAPI +ExpungeConsoleCommandHistoryW(LPCWSTR lpExeName) +{ + return IntExpungeConsoleCommandHistory(lpExeName, TRUE); +} + +/* + * @implemented (Undocumented) + */ +BOOL +WINAPI +ExpungeConsoleCommandHistoryA(LPCSTR lpExeName) +{ + return IntExpungeConsoleCommandHistory(lpExeName, FALSE); +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasW(LPWSTR lpSource, + LPWSTR lpTargetBuffer, + DWORD TargetBufferLength, + LPWSTR lpExeName) +{ + PCSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest; + NTSTATUS Status; + ULONG Size; + ULONG ExeLength; + ULONG SourceLength; + ULONG RequestLength; + WCHAR * Ptr; + + DPRINT("GetConsoleAliasW entered lpSource %S lpExeName %S\n", lpSource, lpExeName); + + if (lpTargetBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_ALIAS, CSR_CONSOLE); + + ExeLength = wcslen(lpExeName) + 1; + SourceLength = wcslen(lpSource) + 1; + + Size = (ExeLength + SourceLength) * sizeof(WCHAR); + + RequestLength = Size + sizeof(CSR_API_MESSAGE); + Request = RtlAllocateHeap(GetProcessHeap(), 0, RequestLength); + if (Request == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + CaptureBuffer = CsrAllocateCaptureBuffer(1, TargetBufferLength); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + RtlFreeHeap(GetProcessHeap(), 0, Request); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Request->Data.GetConsoleAlias.TargetBuffer = NULL; + + CsrCaptureMessageBuffer(CaptureBuffer, + NULL, + TargetBufferLength, + (PVOID*)&Request->Data.GetConsoleAlias.TargetBuffer); + + Request->Data.GetConsoleAlias.TargetBufferLength = TargetBufferLength; + + Ptr = (LPWSTR)((ULONG_PTR)Request + sizeof(CSR_API_MESSAGE)); + wcscpy(Ptr, lpSource); + Ptr += SourceLength; + wcscpy(Ptr, lpExeName); + + Request->Data.GetConsoleAlias.ExeLength = ExeLength; + Request->Data.GetConsoleAlias.SourceLength = SourceLength; + + Status = CsrClientCallServer(Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE) + Size); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(Status); + return 0; + } + + wcscpy(lpTargetBuffer, Request->Data.GetConsoleAlias.TargetBuffer); + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrFreeCaptureBuffer(CaptureBuffer); + + return Request->Data.GetConsoleAlias.BytesWritten; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasA(LPSTR lpSource, + LPSTR lpTargetBuffer, + DWORD TargetBufferLength, + LPSTR lpExeName) +{ + LPWSTR lpwSource; + LPWSTR lpwExeName; + LPWSTR lpwTargetBuffer; + UINT dwSourceSize; + UINT dwExeNameSize; + UINT dwResult; + + DPRINT("GetConsoleAliasA entered\n"); + + if (lpTargetBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + dwSourceSize = (strlen(lpSource)+1) * sizeof(WCHAR); + lpwSource = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSourceSize); + if (lpwSource == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + MultiByteToWideChar(CP_ACP, 0, lpSource, -1, lpwSource, dwSourceSize); + + dwExeNameSize = (strlen(lpExeName)+1) * sizeof(WCHAR); + lpwExeName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwExeNameSize); + if (lpwExeName == NULL) + { + HeapFree(GetProcessHeap(), 0, lpwSource); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + MultiByteToWideChar(CP_ACP, 0, lpExeName, -1, lpwExeName, dwExeNameSize); + + lpwTargetBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, TargetBufferLength * sizeof(WCHAR)); + if (lpwTargetBuffer == NULL) + { + HeapFree(GetProcessHeap(), 0, lpwSource); + HeapFree(GetProcessHeap(), 0, lpwExeName); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + dwResult = GetConsoleAliasW(lpwSource, lpwTargetBuffer, TargetBufferLength * sizeof(WCHAR), lpwExeName); + + HeapFree(GetProcessHeap(), 0, lpwSource); + HeapFree(GetProcessHeap(), 0, lpwExeName); + + if (dwResult) + dwResult = WideCharToMultiByte(CP_ACP, 0, lpwTargetBuffer, dwResult / sizeof(WCHAR), lpTargetBuffer, TargetBufferLength, NULL, NULL); + + HeapFree(GetProcessHeap(), 0, lpwTargetBuffer); + + return dwResult; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasExesW(LPWSTR lpExeNameBuffer, + DWORD ExeNameBufferLength) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest; + NTSTATUS Status; + + DPRINT("GetConsoleAliasExesW entered\n"); + + CaptureBuffer = CsrAllocateCaptureBuffer(1, ExeNameBufferLength); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_ALIASES_EXES, CSR_CONSOLE); + CsrAllocateMessagePointer(CaptureBuffer, + ExeNameBufferLength, + (PVOID*)&Request.Data.GetConsoleAliasesExes.ExeNames); + Request.Data.GetConsoleAliasesExes.Length = ExeNameBufferLength; + + Status = CsrClientCallServer(&Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + CsrFreeCaptureBuffer(CaptureBuffer); + return 0; + } + + memcpy(lpExeNameBuffer, + Request.Data.GetConsoleAliasesExes.ExeNames, + Request.Data.GetConsoleAliasesExes.BytesWritten); + + CsrFreeCaptureBuffer(CaptureBuffer); + return Request.Data.GetConsoleAliasesExes.BytesWritten; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasExesA(LPSTR lpExeNameBuffer, + DWORD ExeNameBufferLength) +{ + LPWSTR lpwExeNameBuffer; + DWORD dwResult; + + DPRINT("GetConsoleAliasExesA entered\n"); + + lpwExeNameBuffer = HeapAlloc(GetProcessHeap(), 0, ExeNameBufferLength * sizeof(WCHAR)); + + dwResult = GetConsoleAliasExesW(lpwExeNameBuffer, ExeNameBufferLength * sizeof(WCHAR)); + + if (dwResult) + dwResult = WideCharToMultiByte(CP_ACP, 0, lpwExeNameBuffer, dwResult / sizeof(WCHAR), lpExeNameBuffer, ExeNameBufferLength, NULL, NULL); + + HeapFree(GetProcessHeap(), 0, lpwExeNameBuffer); + return dwResult; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasExesLengthW(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + DPRINT("GetConsoleAliasExesLengthW entered\n"); + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_ALIASES_EXES_LENGTH, CSR_CONSOLE); + Request.Data.GetConsoleAliasesExesLength.Length = 0; + + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return Request.Data.GetConsoleAliasesExesLength.Length; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasExesLengthA(VOID) +{ + DWORD dwLength; + + DPRINT("GetConsoleAliasExesLengthA entered\n"); + + dwLength = GetConsoleAliasExesLengthW(); + + if (dwLength) + dwLength /= sizeof(WCHAR); + + return dwLength; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasesW(LPWSTR AliasBuffer, + DWORD AliasBufferLength, + LPWSTR ExeName) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + DWORD dwLength; + + DPRINT("GetConsoleAliasesW entered\n"); + + dwLength = GetConsoleAliasesLengthW(ExeName); + if (!dwLength || dwLength > AliasBufferLength) + return 0; + + CsrRequest = MAKE_CSR_API(GET_ALL_CONSOLE_ALIASES, CSR_CONSOLE); + Request.Data.GetAllConsoleAlias.AliasBuffer = AliasBuffer; + Request.Data.GetAllConsoleAlias.AliasBufferLength = AliasBufferLength; + Request.Data.GetAllConsoleAlias.lpExeName = ExeName; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return Request.Data.GetAllConsoleAlias.BytesWritten / sizeof(WCHAR); +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasesA(LPSTR AliasBuffer, + DWORD AliasBufferLength, + LPSTR ExeName) +{ + DWORD dwRetVal = 0; + LPWSTR lpwExeName = NULL; + LPWSTR lpwAliasBuffer; + + DPRINT("GetConsoleAliasesA entered\n"); + + if (ExeName) + BasepAnsiStringToHeapUnicodeString(ExeName, (LPWSTR*) &lpwExeName); + + lpwAliasBuffer = HeapAlloc(GetProcessHeap(), 0, AliasBufferLength * sizeof(WCHAR)); + + dwRetVal = GetConsoleAliasesW(lpwAliasBuffer, AliasBufferLength, lpwExeName); + + if (lpwExeName) + RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpwExeName); + + if (dwRetVal) + dwRetVal = WideCharToMultiByte(CP_ACP, 0, lpwAliasBuffer, dwRetVal, AliasBuffer, AliasBufferLength, NULL, NULL); + + HeapFree(GetProcessHeap(), 0, lpwAliasBuffer); + return dwRetVal; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasesLengthW(LPWSTR lpExeName) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + DPRINT("GetConsoleAliasesLengthW entered\n"); + + CsrRequest = MAKE_CSR_API(GET_ALL_CONSOLE_ALIASES_LENGTH, CSR_CONSOLE); + Request.Data.GetAllConsoleAliasesLength.lpExeName = lpExeName; + Request.Data.GetAllConsoleAliasesLength.Length = 0; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return Request.Data.GetAllConsoleAliasesLength.Length; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetConsoleAliasesLengthA(LPSTR lpExeName) +{ + DWORD dwRetVal = 0; + LPWSTR lpExeNameW = NULL; + + if (lpExeName) + BasepAnsiStringToHeapUnicodeString(lpExeName, (LPWSTR*) &lpExeNameW); + + dwRetVal = GetConsoleAliasesLengthW(lpExeNameW); + if (dwRetVal) + dwRetVal /= sizeof(WCHAR); + + /* Clean up */ + if (lpExeNameW) + RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpExeNameW); + + return dwRetVal; +} + + +static DWORD +IntGetConsoleCommandHistory(LPVOID lpHistory, DWORD cbHistory, LPCVOID lpExeName, BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(GET_COMMAND_HISTORY, CSR_CONSOLE); + NTSTATUS Status; + DWORD HistoryLength = cbHistory * (bUnicode ? 1 : sizeof(WCHAR)); + + if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + CaptureBuffer = CsrAllocateCaptureBuffer(2, IntStringSize(lpExeName, bUnicode) + + HistoryLength); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + &Request.Data.GetCommandHistory.ExeName); + Request.Data.GetCommandHistory.Length = HistoryLength; + CsrAllocateMessagePointer(CaptureBuffer, HistoryLength, + (PVOID*)&Request.Data.GetCommandHistory.History); + + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(Status); + return 0; + } + + if (bUnicode) + { + memcpy(lpHistory, + Request.Data.GetCommandHistory.History, + Request.Data.GetCommandHistory.Length); + } + else + { + WideCharToMultiByte(CP_ACP, 0, + Request.Data.GetCommandHistory.History, + Request.Data.GetCommandHistory.Length / sizeof(WCHAR), + lpHistory, + cbHistory, + NULL, NULL); + } + CsrFreeCaptureBuffer(CaptureBuffer); + return Request.Data.GetCommandHistory.Length; +} + +/* + * @implemented (Undocumented) + */ +DWORD +WINAPI +GetConsoleCommandHistoryW(LPWSTR lpHistory, + DWORD cbHistory, + LPCWSTR lpExeName) +{ + return IntGetConsoleCommandHistory(lpHistory, cbHistory, lpExeName, TRUE); +} + +/* + * @implemented (Undocumented) + */ +DWORD +WINAPI +GetConsoleCommandHistoryA(LPSTR lpHistory, + DWORD cbHistory, + LPCSTR lpExeName) +{ + return IntGetConsoleCommandHistory(lpHistory, cbHistory, lpExeName, FALSE); +} + + +static DWORD +IntGetConsoleCommandHistoryLength(LPCVOID lpExeName, BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(GET_COMMAND_HISTORY_LENGTH, CSR_CONSOLE); + NTSTATUS Status; + + if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + &Request.Data.GetCommandHistoryLength.ExeName); + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + CsrFreeCaptureBuffer(CaptureBuffer); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return 0; + } + return Request.Data.GetCommandHistoryLength.Length; +} + +/* + * @implemented (Undocumented) + */ +DWORD +WINAPI +GetConsoleCommandHistoryLengthW(LPCWSTR lpExeName) +{ + return IntGetConsoleCommandHistoryLength(lpExeName, TRUE); +} + +/* + * @implemented (Undocumented) + */ +DWORD +WINAPI +GetConsoleCommandHistoryLengthA(LPCSTR lpExeName) +{ + return IntGetConsoleCommandHistoryLength(lpExeName, FALSE) / sizeof(WCHAR); +} + + +/* + * @unimplemented + */ +INT +WINAPI +GetConsoleDisplayMode(LPDWORD lpdwMode) + /* + * FUNCTION: Get the console display mode + * ARGUMENTS: + * lpdwMode - Address of variable that receives the current value + * of display mode + * STATUS: Undocumented + */ +{ + DPRINT1("GetConsoleDisplayMode(0x%x) UNIMPLEMENTED!\n", lpdwMode); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * @unimplemented (Undocumented) + */ +DWORD +WINAPI +GetConsoleFontInfo(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + DPRINT1("GetConsoleFontInfo(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * @unimplemented + */ +COORD +WINAPI +GetConsoleFontSize(HANDLE hConsoleOutput, + DWORD nFont) +{ + COORD Empty = {0, 0}; + DPRINT1("GetConsoleFontSize(0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, nFont); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return Empty; +} + + +/* + * @implemented (Undocumented) + */ +DWORD +WINAPI +GetConsoleHardwareState(HANDLE hConsole, + DWORD Flags, + PDWORD State) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SETGET_CONSOLE_HW_STATE, CSR_CONSOLE); + Request.Data.ConsoleHardwareStateRequest.ConsoleHandle = hConsole; + Request.Data.ConsoleHardwareStateRequest.SetGet = CONSOLE_HARDWARE_STATE_GET; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *State = Request.Data.ConsoleHardwareStateRequest.State; + return TRUE; +} + + +/* + * @implemented (Undocumented) + */ +HANDLE +WINAPI +GetConsoleInputWaitHandle(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(GET_INPUT_WAIT_HANDLE, CSR_CONSOLE); + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return Request.Data.GetConsoleInputWaitHandle.InputWaitHandle; +} + + +/* + * @unimplemented + */ +INT +WINAPI +GetCurrentConsoleFont(HANDLE hConsoleOutput, + BOOL bMaximumWindow, + PCONSOLE_FONT_INFO lpConsoleCurrentFont) +{ + DPRINT1("GetCurrentConsoleFont(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, bMaximumWindow, lpConsoleCurrentFont); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * @unimplemented (Undocumented) + */ +ULONG +WINAPI +GetNumberOfConsoleFonts(VOID) +{ + DPRINT1("GetNumberOfConsoleFonts() UNIMPLEMENTED!\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 1; /* FIXME: call csrss.exe */ +} + + +/* + * @unimplemented (Undocumented) + */ +DWORD +WINAPI +InvalidateConsoleDIBits(DWORD Unknown0, + DWORD Unknown1) +{ + DPRINT1("InvalidateConsoleDIBits(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * @unimplemented (Undocumented) + */ +HANDLE +WINAPI +OpenConsoleW(LPCWSTR wsName, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwShareMode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status = STATUS_SUCCESS; + + if (wsName && 0 == _wcsicmp(wsName, L"CONIN$")) + { + CsrRequest = MAKE_CSR_API(GET_INPUT_HANDLE, CSR_NATIVE); + } + else if (wsName && 0 == _wcsicmp(wsName, L"CONOUT$")) + { + CsrRequest = MAKE_CSR_API(GET_OUTPUT_HANDLE, CSR_NATIVE); + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return(INVALID_HANDLE_VALUE); + } + + if (dwDesiredAccess & ~(GENERIC_READ|GENERIC_WRITE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return(INVALID_HANDLE_VALUE); + } + + if (dwShareMode & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return(INVALID_HANDLE_VALUE); + } + + /* Structures for GET_INPUT_HANDLE and GET_OUTPUT_HANDLE requests are identical */ + Request.Data.GetInputHandleRequest.Access = dwDesiredAccess; + Request.Data.GetInputHandleRequest.Inheritable = bInheritHandle; + Request.Data.GetInputHandleRequest.ShareMode = dwShareMode; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + return Request.Data.GetInputHandleRequest.Handle; +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleCursor(DWORD Unknown0, + DWORD Unknown1) +{ + DPRINT1("SetConsoleCursor(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +SetConsoleDisplayMode(HANDLE hOut, + DWORD dwNewMode, + PCOORD lpdwOldMode) + /* + * FUNCTION: Set the console display mode. + * ARGUMENTS: + * hOut - Standard output handle. + * dwNewMode - New mode. + * lpdwOldMode - Address of a variable that receives the old mode. + */ +{ + DPRINT1("SetConsoleDisplayMode(0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n", hOut, dwNewMode, lpdwOldMode); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleFont(DWORD Unknown0, + DWORD Unknown1) +{ + DPRINT1("SetConsoleFont(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @implemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleHardwareState(HANDLE hConsole, + DWORD Flags, + DWORD State) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SETGET_CONSOLE_HW_STATE, CSR_CONSOLE); + Request.Data.ConsoleHardwareStateRequest.ConsoleHandle = hConsole; + Request.Data.ConsoleHardwareStateRequest.SetGet = CONSOLE_HARDWARE_STATE_SET; + Request.Data.ConsoleHardwareStateRequest.State = State; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleKeyShortcuts(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + DPRINT1("SetConsoleKeyShortcuts(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleMaximumWindowSize(DWORD Unknown0, + DWORD Unknown1) +{ + DPRINT1("SetConsoleMaximumWindowSize(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleMenuClose(DWORD Unknown0) +{ + DPRINT1("SetConsoleMenuClose(0x%x) UNIMPLEMENTED!\n", Unknown0); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +static BOOL +IntSetConsoleNumberOfCommands(DWORD dwNumCommands, + LPCVOID lpExeName, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(SET_HISTORY_NUMBER_COMMANDS, CSR_CONSOLE); + NTSTATUS Status; + + if (lpExeName == NULL || !(bUnicode ? *(PWCHAR)lpExeName : *(PCHAR)lpExeName)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + CaptureBuffer = CsrAllocateCaptureBuffer(1, IntStringSize(lpExeName, bUnicode)); + if (!CaptureBuffer) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + IntCaptureMessageString(CaptureBuffer, lpExeName, bUnicode, + &Request.Data.SetHistoryNumberCommands.ExeName); + Request.Data.SetHistoryNumberCommands.NumCommands = dwNumCommands; + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + CsrFreeCaptureBuffer(CaptureBuffer); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + return TRUE; +} + +/* + * @implemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleNumberOfCommandsA(DWORD dwNumCommands, + LPCWSTR lpExeName) +{ + return IntSetConsoleNumberOfCommands(dwNumCommands, lpExeName, FALSE); +} + +/* + * @implemented (Undocumented) + */ +BOOL +WINAPI +SetConsoleNumberOfCommandsW(DWORD dwNumCommands, + LPCSTR lpExeName) +{ + return IntSetConsoleNumberOfCommands(dwNumCommands, lpExeName, TRUE); +} + + +/* + * @unimplemented (Undocumented) + */ +BOOL +WINAPI +SetConsolePalette(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + DPRINT1("SetConsolePalette(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/* + * @unimplemented (Undocumented) + */ +DWORD +WINAPI +ShowConsoleCursor(DWORD Unknown0, + DWORD Unknown1) +{ + DPRINT1("ShowConsoleCursor(0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * FUNCTION: Checks whether the given handle is a valid console handle. + * ARGUMENTS: + * Handle - Handle to be checked + * RETURNS: + * TRUE: Handle is a valid console handle + * FALSE: Handle is not a valid console handle. + * STATUS: Officially undocumented + * + * @implemented + */ +BOOL +WINAPI +VerifyConsoleIoHandle(HANDLE Handle) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(VERIFY_HANDLE, CSR_NATIVE); + Request.Data.VerifyHandleRequest.Handle = Handle; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return (BOOL)NT_SUCCESS(Request.Status); +} + + +/* + * @unimplemented + */ +DWORD +WINAPI +WriteConsoleInputVDMA(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + DPRINT1("WriteConsoleInputVDMA(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * @unimplemented + */ +DWORD +WINAPI +WriteConsoleInputVDMW(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + DPRINT1("WriteConsoleInputVDMW(0x%x, 0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", Unknown0, Unknown1, Unknown2, Unknown3); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* + * @implemented (Undocumented) + */ +BOOL +WINAPI +CloseConsoleHandle(HANDLE Handle) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(CLOSE_HANDLE, CSR_NATIVE); + Request.Data.CloseHandleRequest.Handle = Handle; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +GetStdHandle(DWORD nStdHandle) + /* + * FUNCTION: Get a handle for the standard input, standard output + * and a standard error device. + * ARGUMENTS: + * nStdHandle - Specifies the device for which to return the handle. + * RETURNS: If the function succeeds, the return value is the handle + * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE. + */ +{ + PRTL_USER_PROCESS_PARAMETERS Ppb; + + Ppb = NtCurrentPeb()->ProcessParameters; + switch (nStdHandle) + { + case STD_INPUT_HANDLE: + return Ppb->StandardInput; + + case STD_OUTPUT_HANDLE: + return Ppb->StandardOutput; + + case STD_ERROR_HANDLE: + return Ppb->StandardError; + } + + SetLastError (ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetStdHandle(DWORD nStdHandle, + HANDLE hHandle) + /* + * FUNCTION: Set the handle for the standard input, standard output or + * the standard error device. + * ARGUMENTS: + * nStdHandle - Specifies the handle to be set. + * hHandle - The handle to set. + * RETURNS: TRUE if the function succeeds, FALSE otherwise. + */ +{ + PRTL_USER_PROCESS_PARAMETERS Ppb; + + /* no need to check if hHandle == INVALID_HANDLE_VALUE */ + + Ppb = NtCurrentPeb()->ProcessParameters; + + switch (nStdHandle) + { + case STD_INPUT_HANDLE: + Ppb->StandardInput = hHandle; + return TRUE; + + case STD_OUTPUT_HANDLE: + Ppb->StandardOutput = hHandle; + return TRUE; + + case STD_ERROR_HANDLE: + Ppb->StandardError = hHandle; + return TRUE; + } + + /* windows for whatever reason sets the last error to ERROR_INVALID_HANDLE here */ + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; +} + + +static +BOOL +IntWriteConsole(HANDLE hConsoleOutput, + PVOID lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved, + BOOL bUnicode) +{ + PCSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + USHORT nChars; + ULONG SizeBytes, CharSize; + DWORD Written = 0; + + CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + Request = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE) + min(nNumberOfCharsToWrite, + CSRSS_MAX_WRITE_CONSOLE / CharSize) * CharSize)); + if (Request == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(WRITE_CONSOLE, CSR_CONSOLE); + + while (nNumberOfCharsToWrite > 0) + { + Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleRequest.Unicode = bUnicode; + + nChars = (USHORT)min(nNumberOfCharsToWrite, CSRSS_MAX_WRITE_CONSOLE / CharSize); + Request->Data.WriteConsoleRequest.NrCharactersToWrite = nChars; + + SizeBytes = nChars * CharSize; + + memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, SizeBytes); + + Status = CsrClientCallServer(Request, + NULL, + CsrRequest, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE) + SizeBytes)); + + if (Status == STATUS_PENDING) + { + WaitForSingleObject(Request->Data.WriteConsoleRequest.UnpauseEvent, INFINITE); + CloseHandle(Request->Data.WriteConsoleRequest.UnpauseEvent); + continue; + } + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + BaseSetLastNTError(Status); + return FALSE; + } + + nNumberOfCharsToWrite -= nChars; + lpBuffer = (PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)SizeBytes); + Written += Request->Data.WriteConsoleRequest.NrCharactersWritten; + } + + if (lpNumberOfCharsWritten != NULL) + { + *lpNumberOfCharsWritten = Written; + } + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + + return TRUE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleA + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleA(HANDLE hConsoleOutput, + CONST VOID *lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved) +{ + return IntWriteConsole(hConsoleOutput, + (PVOID)lpBuffer, + nNumberOfCharsToWrite, + lpNumberOfCharsWritten, + lpReserved, + FALSE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleW + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleW(HANDLE hConsoleOutput, + CONST VOID *lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved) +{ + return IntWriteConsole(hConsoleOutput, + (PVOID)lpBuffer, + nNumberOfCharsToWrite, + lpNumberOfCharsWritten, + lpReserved, + TRUE); +} + + +static +BOOL +IntReadConsole(HANDLE hConsoleInput, + PVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + PCONSOLE_READCONSOLE_CONTROL pInputControl, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE); + NTSTATUS Status = STATUS_SUCCESS; + ULONG CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + + CaptureBuffer = CsrAllocateCaptureBuffer(1, nNumberOfCharsToRead * CharSize); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrAllocateMessagePointer(CaptureBuffer, + nNumberOfCharsToRead * CharSize, + &Request.Data.ReadConsoleRequest.Buffer); + + Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput; + Request.Data.ReadConsoleRequest.Unicode = bUnicode; + Request.Data.ReadConsoleRequest.NrCharactersToRead = (WORD)nNumberOfCharsToRead; + Request.Data.ReadConsoleRequest.NrCharactersRead = 0; + Request.Data.ReadConsoleRequest.CtrlWakeupMask = 0; + if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) + { + Request.Data.ReadConsoleRequest.NrCharactersRead = pInputControl->nInitialChars; + memcpy(Request.Data.ReadConsoleRequest.Buffer, + lpBuffer, + pInputControl->nInitialChars * sizeof(WCHAR)); + Request.Data.ReadConsoleRequest.CtrlWakeupMask = pInputControl->dwCtrlWakeupMask; + } + + do + { + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(Request.Data.ReadConsoleRequest.EventHandle, + FALSE, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Wait for console input failed!\n"); + break; + } + } + + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + DPRINT1("CSR returned error in ReadConsole\n"); + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(Status); + return FALSE; + } + } + while (Status == STATUS_PENDING); + + memcpy(lpBuffer, + Request.Data.ReadConsoleRequest.Buffer, + Request.Data.ReadConsoleRequest.NrCharactersRead * CharSize); + + if (lpNumberOfCharsRead != NULL) + *lpNumberOfCharsRead = Request.Data.ReadConsoleRequest.NrCharactersRead; + + if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) + pInputControl->dwControlKeyState = Request.Data.ReadConsoleRequest.ControlKeyState; + + CsrFreeCaptureBuffer(CaptureBuffer); + + return TRUE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleA + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleA(HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + PCONSOLE_READCONSOLE_CONTROL pInputControl) +{ + return IntReadConsole(hConsoleInput, + lpBuffer, + nNumberOfCharsToRead, + lpNumberOfCharsRead, + NULL, + FALSE); +} + + +/*-------------------------------------------------------------- + * ReadConsoleW + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleW(HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + PCONSOLE_READCONSOLE_CONTROL pInputControl) +{ + return IntReadConsole(hConsoleInput, + lpBuffer, + nNumberOfCharsToRead, + lpNumberOfCharsRead, + pInputControl, + TRUE); +} + + +/*-------------------------------------------------------------- + * AllocConsole + * + * @implemented + */ +BOOL +WINAPI +AllocConsole(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + HANDLE hStdError; + + if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) + { + DPRINT("AllocConsole: Allocate duplicate console to the same Process\n"); + BaseSetLastNTError (STATUS_OBJECT_NAME_EXISTS); + return FALSE; + } + + Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher; + Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE; + Request.Data.AllocConsoleRequest.Visible = TRUE; + + CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE); + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + NtCurrentPeb()->ProcessParameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console; + + SetStdHandle(STD_INPUT_HANDLE, Request.Data.AllocConsoleRequest.InputHandle); + SetStdHandle(STD_OUTPUT_HANDLE, Request.Data.AllocConsoleRequest.OutputHandle); + + hStdError = DuplicateConsoleHandle(Request.Data.AllocConsoleRequest.OutputHandle, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + + SetStdHandle(STD_ERROR_HANDLE, hStdError); + return TRUE; +} + + +/*-------------------------------------------------------------- + * FreeConsole + * + * @implemented + */ +BOOL +WINAPI +FreeConsole(VOID) +{ + // AG: I'm not sure if this is correct (what happens to std handles?) + // but I just tried to reverse what AllocConsole() does... + + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(FREE_CONSOLE, CSR_CONSOLE); + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetConsoleScreenBufferInfo + * + * @implemented + */ +BOOL +WINAPI +GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, + PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SCREEN_BUFFER_INFO, CSR_CONSOLE); + Request.Data.ScreenBufferInfoRequest.ConsoleHandle = hConsoleOutput; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + *lpConsoleScreenBufferInfo = Request.Data.ScreenBufferInfoRequest.Info; + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleCursorPosition + * + * @implemented + */ +BOOL +WINAPI +SetConsoleCursorPosition(HANDLE hConsoleOutput, + COORD dwCursorPosition) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_CURSOR, CSR_CONSOLE); + Request.Data.SetCursorRequest.ConsoleHandle = hConsoleOutput; + Request.Data.SetCursorRequest.Position = dwCursorPosition; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +static +BOOL +IntFillConsoleOutputCharacter(HANDLE hConsoleOutput, + PVOID cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(FILL_OUTPUT, CSR_CONSOLE); + Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput; + Request.Data.FillOutputRequest.Unicode = bUnicode; + + if(bUnicode) + Request.Data.FillOutputRequest.Char.UnicodeChar = *((WCHAR*)cCharacter); + else + Request.Data.FillOutputRequest.Char.AsciiChar = *((CHAR*)cCharacter); + + Request.Data.FillOutputRequest.Position = dwWriteCoord; + Request.Data.FillOutputRequest.Length = (WORD)nLength; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if(lpNumberOfCharsWritten != NULL) + { + *lpNumberOfCharsWritten = Request.Data.FillOutputRequest.NrCharactersWritten; + } + + return TRUE; +} + +/*-------------------------------------------------------------- + * FillConsoleOutputCharacterA + * + * @implemented + */ +BOOL +WINAPI +FillConsoleOutputCharacterA(HANDLE hConsoleOutput, + CHAR cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten) +{ + return IntFillConsoleOutputCharacter(hConsoleOutput, + &cCharacter, + nLength, + dwWriteCoord, + lpNumberOfCharsWritten, + FALSE); +} + + +/*-------------------------------------------------------------- + * FillConsoleOutputCharacterW + * + * @implemented + */ +BOOL +WINAPI +FillConsoleOutputCharacterW(HANDLE hConsoleOutput, + WCHAR cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten) +{ + return IntFillConsoleOutputCharacter(hConsoleOutput, + &cCharacter, + nLength, + dwWriteCoord, + lpNumberOfCharsWritten, + TRUE); +} + + +static +BOOL +IntPeekConsoleInput(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + NTSTATUS Status; + ULONG Size; + + if (lpBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Size = nLength * sizeof(INPUT_RECORD); + + /* Allocate a Capture Buffer */ + DPRINT("IntPeekConsoleInput: %lx %p\n", Size, lpNumberOfEventsRead); + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrCaptureMessageBuffer(CaptureBuffer, + NULL, + Size, + (PVOID*)&Request.Data.PeekConsoleInputRequest.InputRecord); + + /* Set up the data to send to the Console Server */ + CsrRequest = MAKE_CSR_API(PEEK_CONSOLE_INPUT, CSR_CONSOLE); + Request.Data.PeekConsoleInputRequest.ConsoleHandle = hConsoleInput; + Request.Data.PeekConsoleInputRequest.Unicode = bUnicode; + Request.Data.PeekConsoleInputRequest.Length = nLength; + + /* Call the server */ + Status = CsrClientCallServer(&Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + DPRINT("Server returned: %x\n", Request.Status); + + /* Check for success*/ + if (NT_SUCCESS(Request.Status)) + { + /* Return the number of events read */ + DPRINT("Events read: %lx\n", Request.Data.PeekConsoleInputRequest.Length); + *lpNumberOfEventsRead = Request.Data.PeekConsoleInputRequest.Length; + + /* Copy into the buffer */ + DPRINT("Copying to buffer\n"); + RtlCopyMemory(lpBuffer, + Request.Data.PeekConsoleInputRequest.InputRecord, + sizeof(INPUT_RECORD) * *lpNumberOfEventsRead); + } + else + { + /* Error out */ + *lpNumberOfEventsRead = 0; + BaseSetLastNTError(Request.Status); + } + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return TRUE or FALSE */ + return NT_SUCCESS(Request.Status); +} + +/*-------------------------------------------------------------- + * PeekConsoleInputA + * + * @implemented + */ +BOOL +WINAPI +PeekConsoleInputA(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead) +{ + return IntPeekConsoleInput(hConsoleInput, + lpBuffer, + nLength, + lpNumberOfEventsRead, + FALSE); +} + + +/*-------------------------------------------------------------- + * PeekConsoleInputW + * + * @implemented + */ +BOOL +WINAPI +PeekConsoleInputW(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead) +{ + return IntPeekConsoleInput(hConsoleInput, + lpBuffer, nLength, + lpNumberOfEventsRead, + TRUE); +} + + +static +BOOL +IntReadConsoleInput(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + ULONG Read; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(READ_INPUT, CSR_CONSOLE); + Read = 0; + + while (nLength > 0) + { + Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput; + Request.Data.ReadInputRequest.Unicode = bUnicode; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + if (Read == 0) + { + /* we couldn't read a single record, fail */ + BaseSetLastNTError(Status); + return FALSE; + } + else + { + /* FIXME - fail gracefully in case we already read at least one record? */ + break; + } + } + else if (Status == STATUS_PENDING) + { + if (Read == 0) + { + Status = NtWaitForSingleObject(Request.Data.ReadInputRequest.Event, FALSE, 0); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + break; + } + } + else + { + /* nothing more to read (waiting for more input??), let's just bail */ + break; + } + } + else + { + lpBuffer[Read++] = Request.Data.ReadInputRequest.Input; + nLength--; + + if (!Request.Data.ReadInputRequest.MoreEvents) + { + /* nothing more to read, bail */ + break; + } + } + } + + if (lpNumberOfEventsRead != NULL) + { + *lpNumberOfEventsRead = Read; + } + + return (Read > 0); +} + + +/*-------------------------------------------------------------- + * ReadConsoleInputA + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleInputA(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead) +{ + return IntReadConsoleInput(hConsoleInput, + lpBuffer, + nLength, + lpNumberOfEventsRead, + FALSE); +} + + +/*-------------------------------------------------------------- + * ReadConsoleInputW + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleInputW(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead) +{ + return IntReadConsoleInput(hConsoleInput, + lpBuffer, + nLength, + lpNumberOfEventsRead, + TRUE); +} + + +static +BOOL +IntWriteConsoleInput(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + NTSTATUS Status; + DWORD Size; + + if (lpBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Size = nLength * sizeof(INPUT_RECORD); + + /* Allocate a Capture Buffer */ + DPRINT("IntWriteConsoleInput: %lx %p\n", Size, lpNumberOfEventsWritten); + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrCaptureMessageBuffer(CaptureBuffer, + lpBuffer, + Size, + (PVOID*)&Request.Data.WriteConsoleInputRequest.InputRecord); + + /* Set up the data to send to the Console Server */ + CsrRequest = MAKE_CSR_API(WRITE_CONSOLE_INPUT, CSR_CONSOLE); + Request.Data.WriteConsoleInputRequest.ConsoleHandle = hConsoleInput; + Request.Data.WriteConsoleInputRequest.Unicode = bUnicode; + Request.Data.WriteConsoleInputRequest.Length = nLength; + + /* Call the server */ + Status = CsrClientCallServer(&Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + DPRINT("Server returned: %x\n", Request.Status); + + /* Check for success*/ + if (NT_SUCCESS(Request.Status)) + { + /* Return the number of events read */ + DPRINT("Events read: %lx\n", Request.Data.WriteConsoleInputRequest.Length); + *lpNumberOfEventsWritten = Request.Data.WriteConsoleInputRequest.Length; + } + else + { + /* Error out */ + *lpNumberOfEventsWritten = 0; + BaseSetLastNTError(Request.Status); + } + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return TRUE or FALSE */ + return NT_SUCCESS(Request.Status); +} + + +/*-------------------------------------------------------------- + * WriteConsoleInputA + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleInputA(HANDLE hConsoleInput, + CONST INPUT_RECORD *lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten) +{ + return IntWriteConsoleInput(hConsoleInput, + (PINPUT_RECORD)lpBuffer, + nLength, + lpNumberOfEventsWritten, + FALSE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleInputW + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleInputW(HANDLE hConsoleInput, + CONST INPUT_RECORD *lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten) +{ + return IntWriteConsoleInput(hConsoleInput, + (PINPUT_RECORD)lpBuffer, + nLength, + lpNumberOfEventsWritten, + TRUE); +} + + +static +BOOL +IntReadConsoleOutput(HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + NTSTATUS Status; + DWORD Size, SizeX, SizeY; + + if (lpBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO); + + /* Allocate a Capture Buffer */ + DPRINT("IntReadConsoleOutput: %lx %p\n", Size, lpReadRegion); + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed with size 0x%x!\n", Size); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrCaptureMessageBuffer(CaptureBuffer, + NULL, + Size, + (PVOID*)&Request.Data.ReadConsoleOutputRequest.CharInfo); + + /* Set up the data to send to the Console Server */ + CsrRequest = MAKE_CSR_API(READ_CONSOLE_OUTPUT, CSR_CONSOLE); + Request.Data.ReadConsoleOutputRequest.ConsoleHandle = hConsoleOutput; + Request.Data.ReadConsoleOutputRequest.Unicode = bUnicode; + Request.Data.ReadConsoleOutputRequest.BufferSize = dwBufferSize; + Request.Data.ReadConsoleOutputRequest.BufferCoord = dwBufferCoord; + Request.Data.ReadConsoleOutputRequest.ReadRegion = *lpReadRegion; + + /* Call the server */ + Status = CsrClientCallServer(&Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + DPRINT("Server returned: %x\n", Request.Status); + + /* Check for success*/ + if (NT_SUCCESS(Request.Status)) + { + /* Copy into the buffer */ + DPRINT("Copying to buffer\n"); + SizeX = Request.Data.ReadConsoleOutputRequest.ReadRegion.Right - + Request.Data.ReadConsoleOutputRequest.ReadRegion.Left + 1; + SizeY = Request.Data.ReadConsoleOutputRequest.ReadRegion.Bottom - + Request.Data.ReadConsoleOutputRequest.ReadRegion.Top + 1; + RtlCopyMemory(lpBuffer, + Request.Data.ReadConsoleOutputRequest.CharInfo, + sizeof(CHAR_INFO) * SizeX * SizeY); + } + else + { + /* Error out */ + BaseSetLastNTError(Request.Status); + } + + /* Return the read region */ + DPRINT("read region: %lx\n", Request.Data.ReadConsoleOutputRequest.ReadRegion); + *lpReadRegion = Request.Data.ReadConsoleOutputRequest.ReadRegion; + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return TRUE or FALSE */ + return NT_SUCCESS(Request.Status); +} + +/*-------------------------------------------------------------- + * ReadConsoleOutputA + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleOutputA(HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion) +{ + return IntReadConsoleOutput(hConsoleOutput, + lpBuffer, + dwBufferSize, + dwBufferCoord, + lpReadRegion, + FALSE); +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputW + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleOutputW(HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion) +{ + return IntReadConsoleOutput(hConsoleOutput, + lpBuffer, + dwBufferSize, + dwBufferCoord, + lpReadRegion, + TRUE); +} + + +static +BOOL +IntWriteConsoleOutput(HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + NTSTATUS Status; + ULONG Size; + + Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO); + + /* Allocate a Capture Buffer */ + DPRINT("IntWriteConsoleOutput: %lx %p\n", Size, lpWriteRegion); + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrCaptureMessageBuffer(CaptureBuffer, + NULL, + Size, + (PVOID*)&Request.Data.WriteConsoleOutputRequest.CharInfo); + + /* Copy from the buffer */ + RtlCopyMemory(Request.Data.WriteConsoleOutputRequest.CharInfo, lpBuffer, Size); + + /* Set up the data to send to the Console Server */ + CsrRequest = MAKE_CSR_API(WRITE_CONSOLE_OUTPUT, CSR_CONSOLE); + Request.Data.WriteConsoleOutputRequest.ConsoleHandle = hConsoleOutput; + Request.Data.WriteConsoleOutputRequest.Unicode = bUnicode; + Request.Data.WriteConsoleOutputRequest.BufferSize = dwBufferSize; + Request.Data.WriteConsoleOutputRequest.BufferCoord = dwBufferCoord; + Request.Data.WriteConsoleOutputRequest.WriteRegion = *lpWriteRegion; + + /* Call the server */ + Status = CsrClientCallServer(&Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + DPRINT("Server returned: %x\n", Request.Status); + + /* Check for success*/ + if (!NT_SUCCESS(Request.Status)) + { + /* Error out */ + BaseSetLastNTError(Request.Status); + } + + /* Return the read region */ + DPRINT("read region: %lx\n", Request.Data.WriteConsoleOutputRequest.WriteRegion); + *lpWriteRegion = Request.Data.WriteConsoleOutputRequest.WriteRegion; + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return TRUE or FALSE */ + return NT_SUCCESS(Request.Status); +} + +/*-------------------------------------------------------------- + * WriteConsoleOutputA + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleOutputA(HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion) +{ + return IntWriteConsoleOutput(hConsoleOutput, + lpBuffer, + dwBufferSize, + dwBufferCoord, + lpWriteRegion, + FALSE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputW + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleOutputW(HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion) +{ + return IntWriteConsoleOutput(hConsoleOutput, + lpBuffer, + dwBufferSize, + dwBufferCoord, + lpWriteRegion, + TRUE); +} + + +static +BOOL +IntReadConsoleOutputCharacter(HANDLE hConsoleOutput, + PVOID lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead, + BOOL bUnicode) +{ + PCSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + ULONG nChars, SizeBytes, CharSize; + DWORD CharsRead = 0; + + CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + + nChars = min(nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR) / CharSize; + SizeBytes = nChars * CharSize; + + Request = RtlAllocateHeap(RtlGetProcessHeap(), 0, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) + + min (nChars, CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR / CharSize) * CharSize)); + if (Request == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(READ_CONSOLE_OUTPUT_CHAR, CSR_CONSOLE); + Request->Data.ReadConsoleOutputCharRequest.ReadCoord = dwReadCoord; + + while (nLength > 0) + { + DWORD BytesRead; + + Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput; + Request->Data.ReadConsoleOutputCharRequest.Unicode = bUnicode; + Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead = min(nLength, nChars); + SizeBytes = Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead * CharSize; + + Status = CsrClientCallServer(Request, + NULL, + CsrRequest, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) + SizeBytes)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Request->Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + BaseSetLastNTError(Status); + break; + } + + BytesRead = Request->Data.ReadConsoleOutputCharRequest.CharsRead * CharSize; + memcpy(lpCharacter, Request->Data.ReadConsoleOutputCharRequest.String, BytesRead); + lpCharacter = (PVOID)((ULONG_PTR)lpCharacter + (ULONG_PTR)BytesRead); + CharsRead += Request->Data.ReadConsoleOutputCharRequest.CharsRead; + nLength -= Request->Data.ReadConsoleOutputCharRequest.CharsRead; + + Request->Data.ReadConsoleOutputCharRequest.ReadCoord = Request->Data.ReadConsoleOutputCharRequest.EndCoord; + } + + if (lpNumberOfCharsRead != NULL) + { + *lpNumberOfCharsRead = CharsRead; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + + return TRUE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputCharacterA + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, + LPSTR lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead) +{ + return IntReadConsoleOutputCharacter(hConsoleOutput, + (PVOID)lpCharacter, + nLength, + dwReadCoord, + lpNumberOfCharsRead, + FALSE); +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputCharacterW + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, + LPWSTR lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead) +{ + return IntReadConsoleOutputCharacter(hConsoleOutput, + (PVOID)lpCharacter, + nLength, + dwReadCoord, + lpNumberOfCharsRead, + TRUE); +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputAttribute + * + * @implemented + */ +BOOL +WINAPI +ReadConsoleOutputAttribute(HANDLE hConsoleOutput, + LPWORD lpAttribute, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfAttrsRead) +{ + PCSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + DWORD Size; + + if (lpNumberOfAttrsRead != NULL) + *lpNumberOfAttrsRead = nLength; + + Request = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB) + + min (nLength, CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)) * sizeof(WORD))); + if (Request == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(READ_CONSOLE_OUTPUT_ATTRIB, CSR_CONSOLE); + + while (nLength != 0) + { + Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput; + Request->Data.ReadConsoleOutputAttribRequest.ReadCoord = dwReadCoord; + + if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)) + Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB / sizeof(WCHAR); + else + Size = nLength; + + Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead = Size; + + Status = CsrClientCallServer(Request, + NULL, + CsrRequest, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB) + Size * sizeof(WORD))); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Request->Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + BaseSetLastNTError(Status); + return FALSE; + } + + memcpy(lpAttribute, Request->Data.ReadConsoleOutputAttribRequest.Attribute, Size * sizeof(WORD)); + lpAttribute += Size; + nLength -= Size; + Request->Data.ReadConsoleOutputAttribRequest.ReadCoord = Request->Data.ReadConsoleOutputAttribRequest.EndCoord; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + + return TRUE; +} + + +static +BOOL +IntWriteConsoleOutputCharacter(HANDLE hConsoleOutput, + PVOID lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten, + BOOL bUnicode) +{ + PCSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + ULONG SizeBytes, CharSize, nChars; + DWORD Written = 0; + + CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); + + nChars = min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR / CharSize); + SizeBytes = nChars * CharSize; + + Request = RtlAllocateHeap(RtlGetProcessHeap(), 0, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) + + min (nChars, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR / CharSize) * CharSize)); + if (Request == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(WRITE_CONSOLE_OUTPUT_CHAR, CSR_CONSOLE); + Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord; + + while (nLength > 0) + { + DWORD BytesWrite; + + Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleOutputCharRequest.Unicode = bUnicode; + Request->Data.WriteConsoleOutputCharRequest.Length = (WORD)min(nLength, nChars); + BytesWrite = Request->Data.WriteConsoleOutputCharRequest.Length * CharSize; + + memcpy(Request->Data.WriteConsoleOutputCharRequest.String, lpCharacter, BytesWrite); + + Status = CsrClientCallServer(Request, + NULL, + CsrRequest, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) + BytesWrite)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + BaseSetLastNTError(Status); + return FALSE; + } + + nLength -= Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten; + lpCharacter = (PVOID)((ULONG_PTR)lpCharacter + (ULONG_PTR)(Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten * CharSize)); + Written += Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten; + + Request->Data.WriteConsoleOutputCharRequest.Coord = Request->Data.WriteConsoleOutputCharRequest.EndCoord; + } + + if (lpNumberOfCharsWritten != NULL) + { + *lpNumberOfCharsWritten = Written; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + + return TRUE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputCharacterA + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, + LPCSTR lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten) +{ + return IntWriteConsoleOutputCharacter(hConsoleOutput, + (PVOID)lpCharacter, + nLength, + dwWriteCoord, + lpNumberOfCharsWritten, + FALSE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputCharacterW + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, + LPCWSTR lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten) +{ + return IntWriteConsoleOutputCharacter(hConsoleOutput, + (PVOID)lpCharacter, + nLength, + dwWriteCoord, + lpNumberOfCharsWritten, + TRUE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputAttribute + * + * @implemented + */ +BOOL +WINAPI +WriteConsoleOutputAttribute(HANDLE hConsoleOutput, + CONST WORD *lpAttribute, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfAttrsWritten) +{ + PCSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + WORD Size; + + Request = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) + + min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)) * sizeof(WORD))); + if (Request == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(WRITE_CONSOLE_OUTPUT_ATTRIB, CSR_CONSOLE); + Request->Data.WriteConsoleOutputAttribRequest.Coord = dwWriteCoord; + + if (lpNumberOfAttrsWritten) + *lpNumberOfAttrsWritten = nLength; + while (nLength) + { + Size = (WORD)min(nLength, CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB / sizeof(WORD)); + Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleOutputAttribRequest.Length = Size; + memcpy(Request->Data.WriteConsoleOutputAttribRequest.Attribute, lpAttribute, Size * sizeof(WORD)); + + Status = CsrClientCallServer(Request, + NULL, + CsrRequest, + max(sizeof(CSR_API_MESSAGE), + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) + Size * sizeof(WORD))); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + BaseSetLastNTError (Status); + return FALSE; + } + nLength -= Size; + lpAttribute += Size; + Request->Data.WriteConsoleOutputAttribRequest.Coord = Request->Data.WriteConsoleOutputAttribRequest.EndCoord; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, Request); + + return TRUE; +} + + +/*-------------------------------------------------------------- + * FillConsoleOutputAttribute + * + * @implemented + */ +BOOL +WINAPI +FillConsoleOutputAttribute(HANDLE hConsoleOutput, + WORD wAttribute, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfAttrsWritten) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(FILL_OUTPUT_ATTRIB, CSR_CONSOLE); + Request.Data.FillOutputAttribRequest.ConsoleHandle = hConsoleOutput; + Request.Data.FillOutputAttribRequest.Attribute = (CHAR)wAttribute; + Request.Data.FillOutputAttribRequest.Coord = dwWriteCoord; + Request.Data.FillOutputAttribRequest.Length = (WORD)nLength; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError ( Status ); + return FALSE; + } + + if (lpNumberOfAttrsWritten) + *lpNumberOfAttrsWritten = nLength; + + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetConsoleMode + * + * @implemented + */ +BOOL +WINAPI +GetConsoleMode(HANDLE hConsoleHandle, + LPDWORD lpMode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_MODE, CSR_CONSOLE); + Request.Data.GetConsoleModeRequest.ConsoleHandle = hConsoleHandle; + + Status = CsrClientCallServer( &Request, NULL, CsrRequest, sizeof( CSR_API_MESSAGE ) ); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError ( Status ); + return FALSE; + } + *lpMode = Request.Data.GetConsoleModeRequest.ConsoleMode; + + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetNumberOfConsoleInputEvents + * + * @implemented + */ +BOOL +WINAPI +GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, + LPDWORD lpNumberOfEvents) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + if (lpNumberOfEvents == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(GET_NUM_INPUT_EVENTS, CSR_CONSOLE); + Request.Data.GetNumInputEventsRequest.ConsoleHandle = hConsoleInput; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpNumberOfEvents = Request.Data.GetNumInputEventsRequest.NumInputEvents; + + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetLargestConsoleWindowSize + * + * @unimplemented + */ +COORD +WINAPI +GetLargestConsoleWindowSize(HANDLE hConsoleOutput) +{ + COORD Coord = {80,25}; + DPRINT1("GetLargestConsoleWindowSize(0x%x) UNIMPLEMENTED!\n", hConsoleOutput); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return Coord; +} + + +/*-------------------------------------------------------------- + * GetConsoleCursorInfo + * + * @implemented + */ +BOOL +WINAPI +GetConsoleCursorInfo(HANDLE hConsoleOutput, + PCONSOLE_CURSOR_INFO lpConsoleCursorInfo) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + if (!lpConsoleCursorInfo) + { + if (!hConsoleOutput) + SetLastError(ERROR_INVALID_HANDLE); + else + SetLastError(ERROR_INVALID_ACCESS); + + return FALSE; + } + + CsrRequest = MAKE_CSR_API(GET_CURSOR_INFO, CSR_CONSOLE); + Request.Data.GetCursorInfoRequest.ConsoleHandle = hConsoleOutput; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + *lpConsoleCursorInfo = Request.Data.GetCursorInfoRequest.Info; + + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetNumberOfConsoleMouseButtons + * + * @unimplemented + */ +BOOL +WINAPI +GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons) +{ + DPRINT1("GetNumberOfConsoleMouseButtons(0x%x) UNIMPLEMENTED!\n", lpNumberOfMouseButtons); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/*-------------------------------------------------------------- + * SetConsoleMode + * + * @implemented + */ +BOOL +WINAPI +SetConsoleMode(HANDLE hConsoleHandle, + DWORD dwMode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_CONSOLE_MODE, CSR_CONSOLE); + Request.Data.SetConsoleModeRequest.ConsoleHandle = hConsoleHandle; + Request.Data.SetConsoleModeRequest.Mode = dwMode; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError ( Status ); + return FALSE; + } + + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleActiveScreenBuffer + * + * @implemented + */ +BOOL +WINAPI +SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_SCREEN_BUFFER, CSR_CONSOLE); + Request.Data.SetScreenBufferRequest.OutputHandle = hConsoleOutput; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/*-------------------------------------------------------------- + * FlushConsoleInputBuffer + * + * @implemented + */ +BOOL +WINAPI +FlushConsoleInputBuffer(HANDLE hConsoleInput) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(FLUSH_INPUT_BUFFER, CSR_CONSOLE); + Request.Data.FlushInputBufferRequest.ConsoleInput = hConsoleInput; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleScreenBufferSize + * + * @implemented + */ +BOOL +WINAPI +SetConsoleScreenBufferSize(HANDLE hConsoleOutput, + COORD dwSize) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_SCREEN_BUFFER_SIZE, CSR_CONSOLE); + Request.Data.SetScreenBufferSize.OutputHandle = hConsoleOutput; + Request.Data.SetScreenBufferSize.Size = dwSize; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/*-------------------------------------------------------------- + * SetConsoleCursorInfo + * + * @implemented + */ +BOOL +WINAPI +SetConsoleCursorInfo(HANDLE hConsoleOutput, + CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_CURSOR_INFO, CSR_CONSOLE); + Request.Data.SetCursorInfoRequest.ConsoleHandle = hConsoleOutput; + Request.Data.SetCursorInfoRequest.Info = *lpConsoleCursorInfo; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +static +BOOL +IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput, + const SMALL_RECT *lpScrollRectangle, + const SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + const CHAR_INFO *lpFill, + BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SCROLL_CONSOLE_SCREEN_BUFFER, CSR_CONSOLE); + Request.Data.ScrollConsoleScreenBufferRequest.ConsoleHandle = hConsoleOutput; + Request.Data.ScrollConsoleScreenBufferRequest.Unicode = bUnicode; + Request.Data.ScrollConsoleScreenBufferRequest.ScrollRectangle = *lpScrollRectangle; + + if (lpClipRectangle != NULL) + { + Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = TRUE; + Request.Data.ScrollConsoleScreenBufferRequest.ClipRectangle = *lpClipRectangle; + } + else + { + Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = FALSE; + } + + Request.Data.ScrollConsoleScreenBufferRequest.DestinationOrigin = dwDestinationOrigin; + Request.Data.ScrollConsoleScreenBufferRequest.Fill = *lpFill; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/*-------------------------------------------------------------- + * ScrollConsoleScreenBufferA + * + * @implemented + */ +BOOL +WINAPI +ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, + CONST SMALL_RECT *lpScrollRectangle, + CONST SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + CONST CHAR_INFO *lpFill) +{ + return IntScrollConsoleScreenBuffer(hConsoleOutput, + (PSMALL_RECT)lpScrollRectangle, + (PSMALL_RECT)lpClipRectangle, + dwDestinationOrigin, + (PCHAR_INFO)lpFill, + FALSE); +} + + +/*-------------------------------------------------------------- + * ScrollConsoleScreenBufferW + * + * @implemented + */ +BOOL +WINAPI +ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, + CONST SMALL_RECT *lpScrollRectangle, + CONST SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + CONST CHAR_INFO *lpFill) +{ + return IntScrollConsoleScreenBuffer(hConsoleOutput, + lpScrollRectangle, + lpClipRectangle, + dwDestinationOrigin, + lpFill, + TRUE); +} + + +/*-------------------------------------------------------------- + * SetConsoleWindowInfo + * + * @unimplemented + */ +BOOL +WINAPI +SetConsoleWindowInfo(HANDLE hConsoleOutput, + BOOL bAbsolute, + CONST SMALL_RECT *lpConsoleWindow) +{ + DPRINT1("SetConsoleWindowInfo(0x%x, 0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, bAbsolute, lpConsoleWindow); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/*-------------------------------------------------------------- + * SetConsoleTextAttribute + * + * @implemented + */ +BOOL +WINAPI +SetConsoleTextAttribute(HANDLE hConsoleOutput, + WORD wAttributes) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_ATTRIB, CSR_CONSOLE); + Request.Data.SetAttribRequest.ConsoleHandle = hConsoleOutput; + Request.Data.SetAttribRequest.Attrib = wAttributes; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +static +BOOL +AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) +{ + PHANDLER_ROUTINE* NewCtrlHandlers = NULL; + + if (HandlerRoutine == NULL) + { + NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE; + return TRUE; + } + + if (NrCtrlHandlers == NrAllocatedHandlers) + { + NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE)); + if (NewCtrlHandlers == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers); + + if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers); + + CtrlHandlers = NewCtrlHandlers; + NrAllocatedHandlers += 4; + } + + ASSERT(NrCtrlHandlers < NrAllocatedHandlers); + + CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine; + return TRUE; +} + + +static +BOOL +RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) +{ + ULONG i; + + if (HandlerRoutine == NULL) + { + NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE; + return TRUE; + } + + for (i = 0; i < NrCtrlHandlers; i++) + { + if (CtrlHandlers[i] == HandlerRoutine) + { + if (i < (NrCtrlHandlers - 1)) + { + memmove(&CtrlHandlers[i], + &CtrlHandlers[i+1], + (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE)); + } + + NrCtrlHandlers--; + return TRUE; + } + } + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, + BOOL Add) +{ + BOOL Ret; + + RtlEnterCriticalSection(&BaseDllDirectoryLock); + if (Add) + { + Ret = AddConsoleCtrlHandler(HandlerRoutine); + } + else + { + Ret = RemoveConsoleCtrlHandler(HandlerRoutine); + } + + RtlLeaveCriticalSection(&BaseDllDirectoryLock); + return(Ret); +} + + +/*-------------------------------------------------------------- + * GenerateConsoleCtrlEvent + * + * @implemented + */ +BOOL +WINAPI +GenerateConsoleCtrlEvent(DWORD dwCtrlEvent, + DWORD dwProcessGroupId) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(GENERATE_CTRL_EVENT, CSR_CONSOLE); + Request.Data.GenerateCtrlEvent.Event = dwCtrlEvent; + Request.Data.GenerateCtrlEvent.ProcessGroup = dwProcessGroupId; + + Status = CsrClientCallServer(&Request, + NULL, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if(!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Request.Status))) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +static DWORD +IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD nSize, BOOL bUnicode) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(GET_TITLE, CSR_CONSOLE); + NTSTATUS Status; + + if (nSize == 0) + return 0; + + Request.Data.GetTitleRequest.Length = nSize * (bUnicode ? 1 : sizeof(WCHAR)); + CaptureBuffer = CsrAllocateCaptureBuffer(1, Request.Data.GetTitleRequest.Length); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + CsrAllocateMessagePointer(CaptureBuffer, + Request.Data.GetTitleRequest.Length, + (PVOID*)&Request.Data.GetTitleRequest.Title); + + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Request.Status))) + { + CsrFreeCaptureBuffer(CaptureBuffer); + BaseSetLastNTError(Status); + return 0; + } + + if (bUnicode) + { + if (nSize >= sizeof(WCHAR)) + wcscpy((LPWSTR)lpConsoleTitle, Request.Data.GetTitleRequest.Title); + } + else + { + if (nSize < Request.Data.GetTitleRequest.Length / sizeof(WCHAR) || + !WideCharToMultiByte(CP_ACP, // ANSI code page + 0, // performance and mapping flags + Request.Data.GetTitleRequest.Title, // address of wide-character string + -1, // number of characters in string + (LPSTR)lpConsoleTitle, // address of buffer for new string + nSize, // size of buffer + NULL, // FAST + NULL)) + { + /* Yes, if the buffer isn't big enough, it returns 0... Bad API */ + *(LPSTR)lpConsoleTitle = '\0'; + Request.Data.GetTitleRequest.Length = 0; + } + } + CsrFreeCaptureBuffer(CaptureBuffer); + + return Request.Data.GetTitleRequest.Length / sizeof(WCHAR); +} + +/*-------------------------------------------------------------- + * GetConsoleTitleW + * + * @implemented + */ +DWORD +WINAPI +GetConsoleTitleW(LPWSTR lpConsoleTitle, + DWORD nSize) +{ + return IntGetConsoleTitle(lpConsoleTitle, nSize, TRUE); +} + +/*-------------------------------------------------------------- + * GetConsoleTitleA + * + * 19990306 EA + * + * @implemented + */ +DWORD +WINAPI +GetConsoleTitleA(LPSTR lpConsoleTitle, + DWORD nSize) +{ + return IntGetConsoleTitle(lpConsoleTitle, nSize, FALSE); +} + + +/*-------------------------------------------------------------- + * SetConsoleTitleW + * + * @implemented + */ +BOOL +WINAPI +SetConsoleTitleW(LPCWSTR lpConsoleTitle) +{ + CSR_API_MESSAGE Request; + PCSR_CAPTURE_BUFFER CaptureBuffer; + ULONG CsrRequest = MAKE_CSR_API(SET_TITLE, CSR_CONSOLE); + NTSTATUS Status; + + Request.Data.SetTitleRequest.Length = wcslen(lpConsoleTitle) * sizeof(WCHAR); + + CaptureBuffer = CsrAllocateCaptureBuffer(1, Request.Data.SetTitleRequest.Length); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)lpConsoleTitle, + Request.Data.SetTitleRequest.Length, + (PVOID*)&Request.Data.SetTitleRequest.Title); + + Status = CsrClientCallServer(&Request, CaptureBuffer, CsrRequest, sizeof(CSR_API_MESSAGE)); + CsrFreeCaptureBuffer(CaptureBuffer); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleTitleA + * + * 19990204 EA Added + * + * @implemented + */ +BOOL +WINAPI +SetConsoleTitleA(LPCSTR lpConsoleTitle) +{ + ULONG Length = strlen(lpConsoleTitle) + 1; + LPWSTR WideTitle = HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR)); + BOOL Ret; + if (!WideTitle) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + MultiByteToWideChar(CP_ACP, 0, lpConsoleTitle, -1, WideTitle, Length); + Ret = SetConsoleTitleW(WideTitle); + HeapFree(GetProcessHeap(), 0, WideTitle); + return Ret; +} + + +/*-------------------------------------------------------------- + * CreateConsoleScreenBuffer + * + * @implemented + */ +HANDLE +WINAPI +CreateConsoleScreenBuffer(DWORD dwDesiredAccess, + DWORD dwShareMode, + CONST SECURITY_ATTRIBUTES *lpSecurityAttributes, + DWORD dwFlags, + LPVOID lpScreenBufferData) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + if (dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE) + || dwShareMode & ~(FILE_SHARE_READ | FILE_SHARE_WRITE) + || dwFlags != CONSOLE_TEXTMODE_BUFFER) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + Request.Data.CreateScreenBufferRequest.Access = dwDesiredAccess; + Request.Data.CreateScreenBufferRequest.ShareMode = dwShareMode; + Request.Data.CreateScreenBufferRequest.Inheritable = + lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE; + + CsrRequest = MAKE_CSR_API(CREATE_SCREEN_BUFFER, CSR_CONSOLE); + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + return Request.Data.CreateScreenBufferRequest.OutputHandle; +} + + +/*-------------------------------------------------------------- + * GetConsoleCP + * + * @implemented + */ +UINT +WINAPI +GetConsoleCP(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_CP, CSR_CONSOLE); + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError (Status); + return 0; + } + + return Request.Data.GetConsoleCodePage.CodePage; +} + + +/*-------------------------------------------------------------- + * SetConsoleCP + * + * @implemented + */ +BOOL +WINAPI +SetConsoleCP(UINT wCodePageID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_CONSOLE_CP, CSR_CONSOLE); + Request.Data.SetConsoleCodePage.CodePage = wCodePageID; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + } + + return NT_SUCCESS(Status); +} + + +/*-------------------------------------------------------------- + * GetConsoleOutputCP + * + * @implemented + */ +UINT +WINAPI +GetConsoleOutputCP(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_OUTPUT_CP, CSR_CONSOLE); + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError (Status); + return 0; + } + + return Request.Data.GetConsoleOutputCodePage.CodePage; +} + + +/*-------------------------------------------------------------- + * SetConsoleOutputCP + * + * @implemented + */ +BOOL +WINAPI +SetConsoleOutputCP(UINT wCodePageID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_CONSOLE_OUTPUT_CP, CSR_CONSOLE); + Request.Data.SetConsoleOutputCodePage.CodePage = wCodePageID; + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + } + + return NT_SUCCESS(Status); +} + + +/*-------------------------------------------------------------- + * GetConsoleProcessList + * + * @implemented + */ +DWORD +WINAPI +GetConsoleProcessList(LPDWORD lpdwProcessList, + DWORD dwProcessCount) +{ + PCSR_CAPTURE_BUFFER CaptureBuffer; + CSR_API_MESSAGE Request; + ULONG CsrRequest; + ULONG nProcesses; + NTSTATUS Status; + + if (lpdwProcessList == NULL || dwProcessCount == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD)); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrRequest = MAKE_CSR_API(GET_PROCESS_LIST, CSR_CONSOLE); + Request.Data.GetProcessListRequest.nMaxIds = dwProcessCount; + CsrAllocateMessagePointer(CaptureBuffer, + dwProcessCount * sizeof(DWORD), + (PVOID*)&Request.Data.GetProcessListRequest.ProcessId); + + Status = CsrClientCallServer(&Request, + CaptureBuffer, + CsrRequest, + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError (Status); + nProcesses = 0; + } + else + { + nProcesses = Request.Data.GetProcessListRequest.nProcessIdsTotal; + if (dwProcessCount >= nProcesses) + { + memcpy(lpdwProcessList, Request.Data.GetProcessListRequest.ProcessId, nProcesses * sizeof(DWORD)); + } + } + + CsrFreeCaptureBuffer(CaptureBuffer); + return nProcesses; +} + + + +/*-------------------------------------------------------------- + * GetConsoleSelectionInfo + * + * @implemented + */ +BOOL +WINAPI +GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest = MAKE_CSR_API(GET_CONSOLE_SELECTION_INFO, CSR_CONSOLE); + NTSTATUS Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpConsoleSelectionInfo = Request.Data.GetConsoleSelectionInfo.Info; + return TRUE; +} + + + +/*-------------------------------------------------------------- + * AttachConsole + * + * @unimplemented + */ +BOOL +WINAPI +AttachConsole(DWORD dwProcessId) +{ + DPRINT1("AttachConsole(0x%x) UNIMPLEMENTED!\n", dwProcessId); + return TRUE; +} + +/*-------------------------------------------------------------- + * GetConsoleWindow + * + * @implemented + */ +HWND +WINAPI +GetConsoleWindow(VOID) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(GET_CONSOLE_WINDOW, CSR_CONSOLE); + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status ) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return (HWND) NULL; + } + + return Request.Data.GetConsoleWindowRequest.WindowHandle; +} + + +/*-------------------------------------------------------------- + * SetConsoleIcon + * + * @implemented + */ +BOOL +WINAPI +SetConsoleIcon(HICON hicon) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest; + NTSTATUS Status; + + CsrRequest = MAKE_CSR_API(SET_CONSOLE_ICON, CSR_CONSOLE); + Request.Data.SetConsoleIconRequest.WindowIcon = hicon; + + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return NT_SUCCESS(Status); +} + + +/****************************************************************************** + * \name SetConsoleInputExeNameW + * \brief Sets the console input file name from a unicode string. + * \param lpInputExeName Pointer to a unicode string with the name. + * \return TRUE if successful, FALSE if unsuccsedful. + * \remarks If lpInputExeName is 0 or the string length is 0 or greater than 255, + * the function fails and sets last error to ERROR_INVALID_PARAMETER. + */ +BOOL +WINAPI +SetConsoleInputExeNameW(LPCWSTR lpInputExeName) +{ + int lenName; + + if (!lpInputExeName + || (lenName = lstrlenW(lpInputExeName)) == 0 + || lenName > INPUTEXENAME_BUFLEN - 1) + { + /* Fail if string is empty or too long */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlEnterCriticalSection(&ConsoleLock); + _SEH2_TRY + { + RtlCopyMemory(InputExeName, lpInputExeName, lenName * sizeof(WCHAR)); + InputExeName[lenName] = L'\0'; + } + _SEH2_FINALLY + { + RtlLeaveCriticalSection(&ConsoleLock); + } + _SEH2_END; + + return TRUE; +} + + +/****************************************************************************** + * \name SetConsoleInputExeNameA + * \brief Sets the console input file name from an ansi string. + * \param lpInputExeName Pointer to an ansi string with the name. + * \return TRUE if successful, FALSE if unsuccsedful. + * \remarks If lpInputExeName is 0 or the string length is 0 or greater than 255, + * the function fails and sets last error to ERROR_INVALID_PARAMETER. + */ +BOOL +WINAPI +SetConsoleInputExeNameA(LPCSTR lpInputExeName) +{ + WCHAR Buffer[INPUTEXENAME_BUFLEN]; + ANSI_STRING InputExeNameA; + UNICODE_STRING InputExeNameU; + NTSTATUS Status; + BOOL Ret; + + RtlInitAnsiString(&InputExeNameA, lpInputExeName); + + if(InputExeNameA.Length == 0 || + InputExeNameA.Length > INPUTEXENAME_BUFLEN - 1) + { + /* Fail if string is empty or too long */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + InputExeNameU.Buffer = Buffer; + InputExeNameU.MaximumLength = sizeof(Buffer); + InputExeNameU.Length = 0; + Status = RtlAnsiStringToUnicodeString(&InputExeNameU, &InputExeNameA, FALSE); + if(NT_SUCCESS(Status)) + { + Ret = SetConsoleInputExeNameW(InputExeNameU.Buffer); + } + else + { + BaseSetLastNTError(Status); + Ret = FALSE; + } + + return Ret; +} + + +/****************************************************************************** + * \name GetConsoleInputExeNameW + * \brief Retrieves the console input file name as unicode string. + * \param nBufferLength Length of the buffer in WCHARs. + * Specify 0 to recieve the needed buffer length. + * \param lpBuffer Pointer to a buffer that recieves the string. + * \return Needed buffer size if \p nBufferLength is 0. + * Otherwise 1 if successful, 2 if buffer is too small. + * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer + * is not big enough. + */ +DWORD +WINAPI +GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer) +{ + int lenName = lstrlenW(InputExeName); + + if (nBufferLength == 0) + { + /* Buffer size is requested, return it */ + return lenName + 1; + } + + if(lenName + 1 > nBufferLength) + { + /* Buffer is not large enough! */ + SetLastError(ERROR_BUFFER_OVERFLOW); + return 2; + } + + RtlEnterCriticalSection(&ConsoleLock); + _SEH2_TRY + { + RtlCopyMemory(lpBuffer, InputExeName, lenName * sizeof(WCHAR)); + lpBuffer[lenName] = '\0'; + } + _SEH2_FINALLY + { + RtlLeaveCriticalSection(&ConsoleLock); + } + _SEH2_END; + + /* Success, return 1 */ + return 1; +} + + +/****************************************************************************** + * \name GetConsoleInputExeNameA + * \brief Retrieves the console input file name as ansi string. + * \param nBufferLength Length of the buffer in CHARs. + * \param lpBuffer Pointer to a buffer that recieves the string. + * \return 1 if successful, 2 if buffer is too small. + * \remarks Sets last error value to ERROR_BUFFER_OVERFLOW if the buffer + * is not big enough. The buffer recieves as much characters as fit. + */ +DWORD +WINAPI +GetConsoleInputExeNameA(DWORD nBufferLength, LPSTR lpBuffer) +{ + WCHAR Buffer[INPUTEXENAME_BUFLEN]; + DWORD Ret; + UNICODE_STRING BufferU; + ANSI_STRING BufferA; + + /* Get the unicode name */ + Ret = GetConsoleInputExeNameW(sizeof(Buffer) / sizeof(Buffer[0]), Buffer); + + /* Initialize strings for conversion */ + RtlInitUnicodeString(&BufferU, Buffer); + BufferA.Length = 0; + BufferA.MaximumLength = nBufferLength; + BufferA.Buffer = lpBuffer; + + /* Convert unicode name to ansi, copying as much chars as fit */ + RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE); + + /* Error handling */ + if(nBufferLength <= BufferU.Length / sizeof(WCHAR)) + { + SetLastError(ERROR_BUFFER_OVERFLOW); + return 2; + } + + return Ret; +} + +BOOL +WINAPI +GetConsoleCharType(HANDLE hConsole, COORD Coord, PDWORD Type) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +GetConsoleCursorMode(HANDLE hConsole, PBOOL pUnknown1, PBOOL pUnknown2) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +GetConsoleNlsMode(HANDLE hConsole, LPDWORD lpMode) +{ + STUB; + return FALSE; +} + + +BOOL +WINAPI +ReadConsoleInputExA(HANDLE hConsole, LPVOID lpBuffer, DWORD dwLen, LPDWORD Unknown1, DWORD Unknown2) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +ReadConsoleInputExW(HANDLE hConsole, LPVOID lpBuffer, DWORD dwLen, LPDWORD Unknown1, DWORD Unknown2) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +RegisterConsoleIME(HWND hWnd, LPDWORD ThreadId) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +RegisterConsoleOS2(BOOL bUnknown) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +SetConsoleCursorMode(HANDLE hConsole, BOOL Unknown1, BOOL Unknown2) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +SetConsoleLocalEUDC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +SetConsoleNlsMode(HANDLE hConsole, DWORD dwMode) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +SetConsoleOS2OemFormat(BOOL bUnknown) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +UnregisterConsoleIME(VOID) +{ + STUB; + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL WINAPI GetConsoleKeyboardLayoutNameA(LPSTR name) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL WINAPI GetConsoleKeyboardLayoutNameW(LPWSTR name) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetLastConsoleEventActive(VOID) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetConsoleCommandHistoryMode(IN DWORD dwMode) +{ + STUB; + return FALSE; +} + + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/copy.c b/dll/win32/kernel32/client/file/copy.c new file mode 100644 index 00000000000..2af2cdfcbbe --- /dev/null +++ b/dll/win32/kernel32/client/file/copy.c @@ -0,0 +1,408 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/copy.c + * PURPOSE: Copying files + * PROGRAMMER: Ariadne (ariadne@xs4all.nl) + * UPDATE HISTORY: + * 01/11/98 Created + * 07/02/99 Moved to seperate file + */ + +/* INCLUDES ****************************************************************/ + +#include +#define NDEBUG +#include + +#if DBG +DEBUG_CHANNEL(kernel32file); +#endif + +/* FUNCTIONS ****************************************************************/ + + +static NTSTATUS +CopyLoop ( + HANDLE FileHandleSource, + HANDLE FileHandleDest, + LARGE_INTEGER SourceFileSize, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + BOOL *pbCancel, + BOOL *KeepDest + ) +{ + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + UCHAR *lpBuffer = NULL; + SIZE_T RegionSize = 0x10000; + LARGE_INTEGER BytesCopied; + DWORD CallbackReason; + DWORD ProgressResult; + BOOL EndOfFileFound; + + *KeepDest = FALSE; + errCode = NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID *)&lpBuffer, + 2, + &RegionSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + + if (NT_SUCCESS(errCode)) + { + BytesCopied.QuadPart = 0; + EndOfFileFound = FALSE; + CallbackReason = CALLBACK_STREAM_SWITCH; + while (! EndOfFileFound && + NT_SUCCESS(errCode) && + (NULL == pbCancel || ! *pbCancel)) + { + if (NULL != lpProgressRoutine) + { + ProgressResult = (*lpProgressRoutine)(SourceFileSize, + BytesCopied, + SourceFileSize, + BytesCopied, + 0, + CallbackReason, + FileHandleSource, + FileHandleDest, + lpData); + switch (ProgressResult) + { + case PROGRESS_CANCEL: + TRACE("Progress callback requested cancel\n"); + errCode = STATUS_REQUEST_ABORTED; + break; + case PROGRESS_STOP: + TRACE("Progress callback requested stop\n"); + errCode = STATUS_REQUEST_ABORTED; + *KeepDest = TRUE; + break; + case PROGRESS_QUIET: + lpProgressRoutine = NULL; + break; + case PROGRESS_CONTINUE: + default: + break; + } + CallbackReason = CALLBACK_CHUNK_FINISHED; + } + if (NT_SUCCESS(errCode)) + { + errCode = NtReadFile(FileHandleSource, + NULL, + NULL, + NULL, + (PIO_STATUS_BLOCK)&IoStatusBlock, + lpBuffer, + RegionSize, + NULL, + NULL); + if (NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel)) + { + errCode = NtWriteFile(FileHandleDest, + NULL, + NULL, + NULL, + (PIO_STATUS_BLOCK)&IoStatusBlock, + lpBuffer, + IoStatusBlock.Information, + NULL, + NULL); + if (NT_SUCCESS(errCode)) + { + BytesCopied.QuadPart += IoStatusBlock.Information; + } + else + { + WARN("Error 0x%08x reading writing to dest\n", errCode); + } + } + else if (!NT_SUCCESS(errCode)) + { + if (STATUS_END_OF_FILE == errCode) + { + EndOfFileFound = TRUE; + errCode = STATUS_SUCCESS; + } + else + { + WARN("Error 0x%08x reading from source\n", errCode); + } + } + } + } + + if (! EndOfFileFound && (NULL != pbCancel && *pbCancel)) + { + TRACE("User requested cancel\n"); + errCode = STATUS_REQUEST_ABORTED; + } + + NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID *)&lpBuffer, + &RegionSize, + MEM_RELEASE); + } + else + { + TRACE("Error 0x%08x allocating buffer of %d bytes\n", errCode, RegionSize); + } + + return errCode; +} + +static NTSTATUS +SetLastWriteTime( + HANDLE FileHandle, + LARGE_INTEGER LastWriteTime + ) +{ + NTSTATUS errCode = STATUS_SUCCESS; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; + + errCode = NtQueryInformationFile (FileHandle, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode); + } + else + { + FileBasic.LastWriteTime.QuadPart = LastWriteTime.QuadPart; + errCode = NtSetInformationFile (FileHandle, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + WARN("Error 0x%0x setting LastWriteTime\n", errCode); + } + } + + return errCode; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CopyFileExW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + BOOL *pbCancel, + DWORD dwCopyFlags + ) +{ + NTSTATUS errCode; + HANDLE FileHandleSource, FileHandleDest; + IO_STATUS_BLOCK IoStatusBlock; + FILE_STANDARD_INFORMATION FileStandard; + FILE_BASIC_INFORMATION FileBasic; + BOOL RC = FALSE; + BOOL KeepDestOnError = FALSE; + DWORD SystemError; + + FileHandleSource = CreateFileW(lpExistingFileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING, + NULL); + if (INVALID_HANDLE_VALUE != FileHandleSource) + { + errCode = NtQueryInformationFile(FileHandleSource, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode); + BaseSetLastNTError(errCode); + } + else + { + errCode = NtQueryInformationFile(FileHandleSource, + &IoStatusBlock,&FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode); + BaseSetLastNTError(errCode); + } + else + { + FileHandleDest = CreateFileW(lpNewFileName, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS, + FileBasic.FileAttributes, + NULL); + if (INVALID_HANDLE_VALUE != FileHandleDest) + { + errCode = CopyLoop(FileHandleSource, + FileHandleDest, + FileStandard.EndOfFile, + lpProgressRoutine, + lpData, + pbCancel, + &KeepDestOnError); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + } + else + { + LARGE_INTEGER t; + + t.QuadPart = FileBasic.LastWriteTime.QuadPart; + errCode = SetLastWriteTime(FileHandleDest, t); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + } + else + { + RC = TRUE; + } + } + NtClose(FileHandleDest); + if (! RC && ! KeepDestOnError) + { + SystemError = GetLastError(); + SetFileAttributesW(lpNewFileName, FILE_ATTRIBUTE_NORMAL); + DeleteFileW(lpNewFileName); + SetLastError(SystemError); + } + } + else + { + WARN("Error %d during opening of dest file\n", GetLastError()); + } + } + } + NtClose(FileHandleSource); + } + else + { + WARN("Error %d during opening of source file\n", GetLastError()); + } + + return RC; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CopyFileExA(IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, + IN LPVOID lpData OPTIONAL, + IN LPBOOL pbCancel OPTIONAL, + IN DWORD dwCopyFlags) +{ + BOOL Result = FALSE; + UNICODE_STRING lpNewFileNameW; + PUNICODE_STRING lpExistingFileNameW; + + lpExistingFileNameW = Basep8BitStringToStaticUnicodeString(lpExistingFileName); + if (!lpExistingFileName) + { + return FALSE; + } + + if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW, lpNewFileName)) + { + Result = CopyFileExW(lpExistingFileNameW->Buffer, + lpNewFileNameW.Buffer, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + + RtlFreeUnicodeString(&lpNewFileNameW); + } + + return Result; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CopyFileA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + BOOL bFailIfExists + ) +{ + return CopyFileExA (lpExistingFileName, + lpNewFileName, + NULL, + NULL, + NULL, + bFailIfExists); +} + + +/* + * @implemented + */ +BOOL +WINAPI +CopyFileW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + BOOL bFailIfExists + ) +{ + return CopyFileExW (lpExistingFileName, + lpNewFileName, + NULL, + NULL, + NULL, + bFailIfExists); +} + + +/* + * @implemented + */ +BOOL +WINAPI +PrivCopyFileExW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + BOOL *pbCancel, + DWORD dwCopyFlags + ) +{ + UNIMPLEMENTED; + return FALSE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/create.c b/dll/win32/kernel32/client/file/create.c new file mode 100644 index 00000000000..a9d6c054760 --- /dev/null +++ b/dll/win32/kernel32/client/file/create.c @@ -0,0 +1,374 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/create.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + * Removed use of SearchPath (not used by Windows) + * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion) + * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +#if DBG +DEBUG_CHANNEL(kernel32file); +#endif + +#define SYMLINK_FLAG_RELATIVE 1 + +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +#define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +HANDLE WINAPI CreateFileA (LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + PWCHAR FileNameW; + HANDLE FileHandle; + + TRACE("CreateFileA(lpFileName %s)\n",lpFileName); + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return INVALID_HANDLE_VALUE; + + FileHandle = CreateFileW (FileNameW, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + return FileHandle; +} + + +/* + * @implemented + */ +HANDLE WINAPI CreateFileW (LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE FileHandle; + NTSTATUS Status; + ULONG FileAttributes, Flags = 0; + PVOID EaBuffer = NULL; + ULONG EaLength = 0; + + if (!lpFileName || !lpFileName[0]) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return INVALID_HANDLE_VALUE; + } + + TRACE("CreateFileW(lpFileName %S)\n",lpFileName); + + /* validate & translate the creation disposition */ + switch (dwCreationDisposition) + { + case CREATE_NEW: + dwCreationDisposition = FILE_CREATE; + break; + + case CREATE_ALWAYS: + dwCreationDisposition = FILE_OVERWRITE_IF; + break; + + case OPEN_EXISTING: + dwCreationDisposition = FILE_OPEN; + break; + + case OPEN_ALWAYS: + dwCreationDisposition = FILE_OPEN_IF; + break; + + case TRUNCATE_EXISTING: + dwCreationDisposition = FILE_OVERWRITE; + break; + + default: + SetLastError(ERROR_INVALID_PARAMETER); + return (INVALID_HANDLE_VALUE); + } + + /* check for console input/output */ + if (0 == _wcsicmp(L"CONOUT$", lpFileName) + || 0 == _wcsicmp(L"CONIN$", lpFileName)) + { + return OpenConsoleW(lpFileName, + dwDesiredAccess, + lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE, + FILE_SHARE_READ | FILE_SHARE_WRITE); + } + + /* validate & translate the flags */ + + /* translate the flags that need no validation */ + if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)) + { + /* yes, nonalert is correct! apc's are not delivered + while waiting for file io to complete */ + Flags |= FILE_SYNCHRONOUS_IO_NONALERT; + } + + if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) + Flags |= FILE_WRITE_THROUGH; + + if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING) + Flags |= FILE_NO_INTERMEDIATE_BUFFERING; + + if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) + Flags |= FILE_RANDOM_ACCESS; + + if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) + Flags |= FILE_SEQUENTIAL_ONLY; + + if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) + Flags |= FILE_DELETE_ON_CLOSE; + + if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) + { + if(dwDesiredAccess & GENERIC_ALL) + Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE; + else + { + if(dwDesiredAccess & GENERIC_READ) + Flags |= FILE_OPEN_FOR_BACKUP_INTENT; + + if(dwDesiredAccess & GENERIC_WRITE) + Flags |= FILE_OPEN_REMOTE_INSTANCE; + } + } + else + Flags |= FILE_NON_DIRECTORY_FILE; + + if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) + Flags |= FILE_OPEN_REPARSE_POINT; + + if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) + Flags |= FILE_OPEN_NO_RECALL; + + FileAttributes = (dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY)); + + /* handle may allways be waited on and querying attributes are allways allowed */ + dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; + + /* FILE_FLAG_POSIX_SEMANTICS is handled later */ + + /* validate & translate the filename */ + if (!RtlDosPathNameToNtPathName_U (lpFileName, + &NtPathU, + NULL, + NULL)) + { + WARN("Invalid path\n"); + SetLastError(ERROR_PATH_NOT_FOUND); + return INVALID_HANDLE_VALUE; + } + + TRACE("NtPathU \'%wZ\'\n", &NtPathU); + + if (hTemplateFile != NULL) + { + FILE_EA_INFORMATION EaInformation; + + for (;;) + { + /* try to get the size of the extended attributes, if we fail just continue + creating the file without copying the attributes! */ + Status = NtQueryInformationFile(hTemplateFile, + &IoStatusBlock, + &EaInformation, + sizeof(FILE_EA_INFORMATION), + FileEaInformation); + if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0)) + { + /* there's extended attributes to read, let's give it a try */ + EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + EaInformation.EaSize); + if (EaBuffer == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtPathU.Buffer); + + /* the template file handle is valid and has extended attributes, + however we seem to lack some memory here. We should fail here! */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return INVALID_HANDLE_VALUE; + } + + Status = NtQueryEaFile(hTemplateFile, + &IoStatusBlock, + EaBuffer, + EaInformation.EaSize, + FALSE, + NULL, + 0, + NULL, + TRUE); + + if (NT_SUCCESS(Status)) + { + /* we successfully read the extended attributes, break the loop + and continue */ + EaLength = EaInformation.EaSize; + break; + } + else + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + EaBuffer); + EaBuffer = NULL; + + if (Status != STATUS_BUFFER_TOO_SMALL) + { + /* unless we just allocated not enough memory, break the loop + and just continue without copying extended attributes */ + break; + } + } + } + else + { + /* we either failed to get the size of the extended attributes or + they're empty, just continue as there's no need to copy + attributes */ + break; + } + } + } + + /* build the object attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + 0, + NULL, + NULL); + + if (lpSecurityAttributes) + { + if(lpSecurityAttributes->bInheritHandle) + ObjectAttributes.Attributes |= OBJ_INHERIT; + + ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; + } + + if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS)) + ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; + + /* perform the call */ + Status = NtCreateFile (&FileHandle, + dwDesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FileAttributes, + dwShareMode, + dwCreationDisposition, + Flags, + EaBuffer, + EaLength); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtPathU.Buffer); + + /* free the extended attributes buffer if allocated */ + if (EaBuffer != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + EaBuffer); + } + + /* error */ + if (!NT_SUCCESS(Status)) + { + /* In the case file creation was rejected due to CREATE_NEW flag + * was specified and file with that name already exists, correct + * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS. + * Note: RtlNtStatusToDosError is not the subject to blame here. + */ + if (Status == STATUS_OBJECT_NAME_COLLISION && + dwCreationDisposition == FILE_CREATE) + { + SetLastError( ERROR_FILE_EXISTS ); + } + else + { + BaseSetLastNTError (Status); + } + + return INVALID_HANDLE_VALUE; + } + + /* + create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED + create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED + */ + if (dwCreationDisposition == FILE_OPEN_IF) + { + SetLastError(IoStatusBlock.Information == FILE_OPENED ? ERROR_ALREADY_EXISTS : 0); + } + else if (dwCreationDisposition == FILE_OVERWRITE_IF) + { + SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : 0); + } + + return FileHandle; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/curdir.c b/dll/win32/kernel32/client/file/curdir.c new file mode 100644 index 00000000000..9d4d2e344fc --- /dev/null +++ b/dll/win32/kernel32/client/file/curdir.c @@ -0,0 +1,388 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/curdir.c + * PURPOSE: Current directory functions + * PROGRAMMER: Eric Kohl + * Filip Navara + * Steven Edwards + * Thomas Weidenmueller + * Gunnar Andre' Dalsnes + * UPDATE HISTORY: + * Created 30/09/98 + */ + + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +#if DBG +DEBUG_CHANNEL(kernel32file); +#endif + +/* GLOBAL VARIABLES **********************************************************/ + +UNICODE_STRING SystemDirectory; +UNICODE_STRING WindowsDirectory; +UNICODE_STRING BaseDefaultPathAppend; +UNICODE_STRING BaseDefaultPath; + + +/* FUNCTIONS *****************************************************************/ + + + + +/* + * @implemented + */ +DWORD +WINAPI +GetCurrentDirectoryA ( + DWORD nBufferLength, + LPSTR lpBuffer + ) +{ + WCHAR BufferW[MAX_PATH]; + DWORD ret; + + ret = GetCurrentDirectoryW(MAX_PATH, BufferW); + + if (!ret) return 0; + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetCurrentDirectoryW ( + DWORD nBufferLength, + LPWSTR lpBuffer + ) +{ + ULONG Length; + + Length = RtlGetCurrentDirectory_U (nBufferLength * sizeof(WCHAR), + lpBuffer); + + return (Length / sizeof (WCHAR)); +} + + + +/* + * @implemented + */ +BOOL +WINAPI +SetCurrentDirectoryA ( + LPCSTR lpPathName + ) +{ + PWCHAR PathNameW; + + TRACE("setcurrdir: %s\n",lpPathName); + + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; + + return SetCurrentDirectoryW(PathNameW); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetCurrentDirectoryW ( + LPCWSTR lpPathName + ) +{ + UNICODE_STRING UnicodeString; + NTSTATUS Status; + + RtlInitUnicodeString (&UnicodeString, + lpPathName); + + Status = RtlSetCurrentDirectory_U (&UnicodeString); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + * + * NOTE: Windows returns a dos/short (8.3) path + */ +DWORD +WINAPI +GetTempPathA ( + DWORD nBufferLength, + LPSTR lpBuffer + ) +{ + WCHAR BufferW[MAX_PATH]; + DWORD ret; + + ret = GetTempPathW(MAX_PATH, BufferW); + + if (!ret) + return 0; + + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); +} + + +/* + * @implemented + * + * ripped from wine + */ +DWORD +WINAPI +GetTempPathW ( + DWORD count, + LPWSTR path + ) +{ + static const WCHAR tmp[] = { 'T', 'M', 'P', 0 }; + static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 }; + static const WCHAR userprofile[] = { 'U','S','E','R','P','R','O','F','I','L','E',0 }; + WCHAR tmp_path[MAX_PATH]; + UINT ret; + + TRACE("%u,%p\n", count, path); + + if (!(ret = GetEnvironmentVariableW( tmp, tmp_path, MAX_PATH )) && + !(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )) && + !(ret = GetEnvironmentVariableW( userprofile, tmp_path, MAX_PATH )) && + !(ret = GetWindowsDirectoryW( tmp_path, MAX_PATH ))) + return 0; + + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + ret = GetFullPathNameW(tmp_path, MAX_PATH, tmp_path, NULL); + if (!ret) return 0; + + if (ret > MAX_PATH - 2) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + if (tmp_path[ret-1] != '\\') + { + tmp_path[ret++] = '\\'; + tmp_path[ret] = '\0'; + } + + ret++; /* add space for terminating 0 */ + + if (count) + { + lstrcpynW(path, tmp_path, count); + if (count >= ret) + ret--; /* return length without 0 */ + else if (count < 4) + path[0] = 0; /* avoid returning ambiguous "X:" */ + } + + TRACE("GetTempPathW returning %u, %S\n", ret, path); + return ret; + +} + + +/* + * @implemented + */ +UINT +WINAPI +GetSystemDirectoryA ( + LPSTR lpBuffer, + UINT uSize + ) +{ + return FilenameU2A_FitOrFail(lpBuffer, uSize, &SystemDirectory); +} + + +/* + * @implemented + */ +UINT +WINAPI +GetSystemDirectoryW ( + LPWSTR lpBuffer, + UINT uSize + ) +{ + ULONG Length; + + Length = SystemDirectory.Length / sizeof (WCHAR); + + if (lpBuffer == NULL) + return Length + 1; + + if (uSize > Length) { + memmove (lpBuffer, + SystemDirectory.Buffer, + SystemDirectory.Length); + lpBuffer[Length] = 0; + + return Length; //good: ret chars excl. nullchar + } + + return Length+1; //bad: ret space needed incl. nullchar +} + +/* + * @implemented + */ +UINT +WINAPI +GetWindowsDirectoryA ( + LPSTR lpBuffer, + UINT uSize + ) +{ + return FilenameU2A_FitOrFail(lpBuffer, uSize, &WindowsDirectory); +} + + +/* + * @implemented + */ +UINT +WINAPI +GetWindowsDirectoryW ( + LPWSTR lpBuffer, + UINT uSize + ) +{ + ULONG Length; + + Length = WindowsDirectory.Length / sizeof (WCHAR); + + if (lpBuffer == NULL) + return Length + 1; + + if (uSize > Length) + { + memmove (lpBuffer, + WindowsDirectory.Buffer, + WindowsDirectory.Length); + lpBuffer[Length] = 0; + + return Length; //good: ret chars excl. nullchar + } + + return Length+1; //bad: ret space needed incl. nullchar +} + +/* + * @implemented + */ +UINT +WINAPI +GetSystemWindowsDirectoryA( + LPSTR lpBuffer, + UINT uSize + ) +{ + return GetWindowsDirectoryA( lpBuffer, uSize ); +} + +/* + * @implemented + */ +UINT +WINAPI +GetSystemWindowsDirectoryW( + LPWSTR lpBuffer, + UINT uSize + ) +{ + return GetWindowsDirectoryW( lpBuffer, uSize ); +} + +/* + * @unimplemented + */ +UINT +WINAPI +GetSystemWow64DirectoryW( + LPWSTR lpBuffer, + UINT uSize + ) +{ +#ifdef _WIN64 + ERR("GetSystemWow64DirectoryW is UNIMPLEMENTED!\n"); + return 0; +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +#endif +} + +/* + * @unimplemented + */ +UINT +WINAPI +GetSystemWow64DirectoryA( + LPSTR lpBuffer, + UINT uSize + ) +{ +#ifdef _WIN64 + WCHAR BufferW[MAX_PATH]; + UINT ret; + + ret = GetSystemWow64DirectoryW(BufferW, MAX_PATH); + + if (!ret) return 0; + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(lpBuffer, uSize, BufferW, ret+1); +#else + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +#endif +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/delete.c b/dll/win32/kernel32/client/file/delete.c new file mode 100644 index 00000000000..d2170673fbc --- /dev/null +++ b/dll/win32/kernel32/client/file/delete.c @@ -0,0 +1,123 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/delete.c + * PURPOSE: Deleting files + * PROGRAMMER: Ariadne (ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +DeleteFileA ( + LPCSTR lpFileName + ) +{ + PWCHAR FileNameW; + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return FALSE; + + return DeleteFileW (FileNameW); +} + + +/* + * @implemented + */ +BOOL +WINAPI +DeleteFileW ( + LPCWSTR lpFileName + ) +{ + FILE_DISPOSITION_INFORMATION FileDispInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE FileHandle; + NTSTATUS Status; + + TRACE("DeleteFileW (lpFileName %S)\n",lpFileName); + + if (!RtlDosPathNameToNtPathName_U (lpFileName, + &NtPathU, + NULL, + NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + TRACE("NtPathU \'%wZ\'\n", &NtPathU); + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtCreateFile (&FileHandle, + DELETE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE, + NULL, + 0); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + WARN("Status 0x%08x\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + FileDispInfo.DeleteFile = TRUE; + + Status = NtSetInformationFile (FileHandle, + &IoStatusBlock, + &FileDispInfo, + sizeof(FILE_DISPOSITION_INFORMATION), + FileDispositionInformation); + if (!NT_SUCCESS(Status)) + { + WARN("Status 0x%08x\n", Status); + NtClose (FileHandle); + BaseSetLastNTError (Status); + return FALSE; + } + + Status = NtClose (FileHandle); + if (!NT_SUCCESS (Status)) + { + WARN("Status 0x%08x\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/deviceio.c b/dll/win32/kernel32/client/file/deviceio.c new file mode 100644 index 00000000000..a00ee9b3d64 --- /dev/null +++ b/dll/win32/kernel32/client/file/deviceio.c @@ -0,0 +1,309 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: kernel32/file/deviceio.c + * PURPOSE: Device I/O Base Client Functionality + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +Beep (DWORD dwFreq, DWORD dwDuration) +{ + HANDLE hBeep; + UNICODE_STRING BeepDevice; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + BEEP_SET_PARAMETERS BeepSetParameters; + NTSTATUS Status; + + /* check the parameters */ + if ((dwFreq >= 0x25 && dwFreq <= 0x7FFF) || + (dwFreq == 0x0 && dwDuration == 0x0)) + { + /* open the device */ + RtlInitUnicodeString(&BeepDevice, + L"\\Device\\Beep"); + + InitializeObjectAttributes(&ObjectAttributes, + &BeepDevice, + 0, + NULL, + NULL); + + Status = NtCreateFile(&hBeep, + FILE_READ_DATA | FILE_WRITE_DATA, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (NT_SUCCESS(Status)) + { + /* Set beep data */ + BeepSetParameters.Frequency = dwFreq; + BeepSetParameters.Duration = dwDuration; + + Status = NtDeviceIoControlFile(hBeep, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_BEEP_SET, + &BeepSetParameters, + sizeof(BEEP_SET_PARAMETERS), + NULL, + 0); + + /* do an alertable wait if necessary */ + if (NT_SUCCESS(Status) && + (dwFreq != 0x0 || dwDuration != 0x0) && dwDuration != MAXDWORD) + { + SleepEx(dwDuration, + TRUE); + } + + NtClose(hBeep); + } + } + else + Status = STATUS_INVALID_PARAMETER; + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DeviceIoControl(IN HANDLE hDevice, + IN DWORD dwIoControlCode, + IN LPVOID lpInBuffer OPTIONAL, + IN DWORD nInBufferSize OPTIONAL, + OUT LPVOID lpOutBuffer OPTIONAL, + IN DWORD nOutBufferSize OPTIONAL, + OUT LPDWORD lpBytesReturned OPTIONAL, + IN LPOVERLAPPED lpOverlapped OPTIONAL) +{ + BOOL FsIoCtl; + NTSTATUS Status; + PVOID ApcContext; + IO_STATUS_BLOCK Iosb; + + /* Check what kind of IOCTL to send */ + FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM); + + /* CHeck for async */ + if (lpOverlapped != NULL) + { + /* Set pending status */ + lpOverlapped->Internal = STATUS_PENDING; + + + /* Check if there's an APC context */ + ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); + + + /* Send file system control? */ + if (FsIoCtl) + { + /* Send it */ + Status = NtFsControlFile(hDevice, + lpOverlapped->hEvent, + NULL, + ApcContext, + (PIO_STATUS_BLOCK)lpOverlapped, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + else + { + /* Otherwise send a device control */ + Status = NtDeviceIoControlFile(hDevice, + lpOverlapped->hEvent, + NULL, + ApcContext, + (PIO_STATUS_BLOCK)lpOverlapped, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + + /* Check for or information instead of failure */ + if (!(NT_ERROR(Status)) && (lpBytesReturned)) + { + /* Protect with SEH */ + _SEH2_TRY + { + /* Return the bytes */ + *lpBytesReturned = lpOverlapped->InternalHigh; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return zero bytes */ + *lpBytesReturned = 0; + } + _SEH2_END; + } + + /* Now check for any kind of failure except pending*/ + if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING)) + { + /* Fail */ + BaseSetLastNTError(Status); + return FALSE; + } + } + else + { + /* Sync case -- send file system code? */ + if (FsIoCtl) + { + /* Do it */ + Status = NtFsControlFile(hDevice, + NULL, + NULL, + NULL, + &Iosb, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + else + { + /* Send device code instead */ + Status = NtDeviceIoControlFile(hDevice, + NULL, + NULL, + NULL, + &Iosb, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + + /* Now check if the operation isn't done yet */ + if (Status == STATUS_PENDING) + { + /* Wait for it and get the final status */ + Status = NtWaitForSingleObject(hDevice, FALSE, NULL); + if (NT_SUCCESS(Status)) Status = Iosb.Status; + } + + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Return the byte count */ + *lpBytesReturned = Iosb.Information; + } + else + { + /* Check for informational or warning failure */ + if (!NT_ERROR(Status)) *lpBytesReturned = Iosb.Information; + + /* Return a failure */ + BaseSetLastNTError(Status); + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetOverlappedResult(IN HANDLE hFile, + IN LPOVERLAPPED lpOverlapped, + OUT LPDWORD lpNumberOfBytesTransferred, + IN BOOL bWait) +{ + DWORD WaitStatus; + HANDLE hObject; + + + /* Check for pending operation */ + if (lpOverlapped->Internal == STATUS_PENDING) + { + /* Check if the caller is okay with waiting */ + if (!bWait) + { + /* Set timeout */ + WaitStatus = WAIT_TIMEOUT; + } + else + { + /* Wait for the result */ + hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile; + WaitStatus = WaitForSingleObject(hObject, INFINITE); + } + + + /* Check for timeout */ + if (WaitStatus == WAIT_TIMEOUT) + { + /* We have to override the last error with INCOMPLETE instead */ + SetLastError(ERROR_IO_INCOMPLETE); + return FALSE; + } + + + /* Fail if we had an error -- the last error is already set */ + if (WaitStatus != 0) return FALSE; + } + + + /* Return bytes transferred */ + *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh; + + + /* Check for failure during I/O */ + if (!NT_SUCCESS(lpOverlapped->Internal)) + { + /* Set the error and fail */ + BaseSetLastNTError(lpOverlapped->Internal); + return FALSE; + } + + + /* All done */ + return TRUE; +} + +/* EOF */ + diff --git a/dll/win32/kernel32/client/file/dir.c b/dll/win32/kernel32/client/file/dir.c new file mode 100644 index 00000000000..6ba996c345a --- /dev/null +++ b/dll/win32/kernel32/client/file/dir.c @@ -0,0 +1,1376 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/dir.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* + * NOTES: Changed to using ZwCreateFile + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +UNICODE_STRING BaseDllDirectory = {0, 0, NULL}; + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +CreateDirectoryA ( + LPCSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + PWCHAR PathNameW; + + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; + + return CreateDirectoryW (PathNameW, + lpSecurityAttributes); +} + + +/* + * @implemented + */ +BOOL +WINAPI +CreateDirectoryExA ( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + PWCHAR TemplateDirectoryW; + PWCHAR NewDirectoryW; + BOOL ret; + + if (!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, TRUE))) + return FALSE; + + if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, FALSE))) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + TemplateDirectoryW); + return FALSE; + } + + ret = CreateDirectoryExW (TemplateDirectoryW, + NewDirectoryW, + lpSecurityAttributes); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + TemplateDirectoryW); + + return ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CreateDirectoryW ( + LPCWSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE DirectoryHandle = NULL; + NTSTATUS Status; + + TRACE ("lpPathName %S lpSecurityAttributes %p\n", + lpPathName, lpSecurityAttributes); + + if (!RtlDosPathNameToNtPathName_U (lpPathName, + &NtPathU, + NULL, + NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL)); + + Status = NtCreateFile (&DirectoryHandle, + FILE_LIST_DIRECTORY | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, + NULL, + 0); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + WARN("NtCreateFile failed with Status %lx\n", Status); + BaseSetLastNTError(Status); + return FALSE; + } + + NtClose (DirectoryHandle); + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CreateDirectoryExW ( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU, NtTemplatePathU; + HANDLE DirectoryHandle = NULL; + HANDLE TemplateHandle = NULL; + FILE_EA_INFORMATION EaInformation; + FILE_BASIC_INFORMATION FileBasicInfo; + NTSTATUS Status; + ULONG OpenOptions, CreateOptions; + ACCESS_MASK DesiredAccess; + BOOLEAN ReparsePoint = FALSE; + PVOID EaBuffer = NULL; + ULONG EaLength = 0; + + OpenOptions = FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | + FILE_OPEN_FOR_BACKUP_INTENT; + CreateOptions = FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT; + DesiredAccess = FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | + FILE_READ_ATTRIBUTES; + + TRACE ("lpTemplateDirectory %ws lpNewDirectory %ws lpSecurityAttributes %p\n", + lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes); + + /* + * Translate the template directory path + */ + + if (!RtlDosPathNameToNtPathName_U (lpTemplateDirectory, + &NtTemplatePathU, + NULL, + NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtTemplatePathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* + * Open the template directory + */ + +OpenTemplateDir: + Status = NtOpenFile (&TemplateHandle, + FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_READ_EA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + OpenOptions); + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_INVALID_PARAMETER && + (OpenOptions & FILE_OPEN_REPARSE_POINT)) + { + /* Some FSs (FAT) don't support reparse points, try opening + the directory without FILE_OPEN_REPARSE_POINT */ + OpenOptions &= ~FILE_OPEN_REPARSE_POINT; + + TRACE("Reparse points not supported, try with less options\n"); + + /* try again */ + goto OpenTemplateDir; + } + else + { + WARN("Failed to open the template directory: 0x%x\n", Status); + goto CleanupNoNtPath; + } + } + + /* + * Translate the new directory path and check if they're the same + */ + + if (!RtlDosPathNameToNtPathName_U (lpNewDirectory, + &NtPathU, + NULL, + NULL)) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + goto CleanupNoNtPath; + } + + if (RtlEqualUnicodeString(&NtPathU, + &NtTemplatePathU, + TRUE)) + { + WARN("Both directory paths are the same!\n"); + Status = STATUS_OBJECT_NAME_INVALID; + goto Cleanup; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL)); + + /* + * Query the basic file attributes from the template directory + */ + + /* Make sure FILE_ATTRIBUTE_NORMAL is used in case the information + isn't set by the FS */ + FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; + Status = NtQueryInformationFile(TemplateHandle, + &IoStatusBlock, + &FileBasicInfo, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + WARN("Failed to query the basic directory attributes\n"); + goto Cleanup; + } + + /* clear the reparse point attribute if present. We're going to set the + reparse point later which will cause the attribute to be set */ + if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + { + FileBasicInfo.FileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT; + + /* writing the extended attributes requires the FILE_WRITE_DATA + access right */ + DesiredAccess |= FILE_WRITE_DATA; + + CreateOptions |= FILE_OPEN_REPARSE_POINT; + ReparsePoint = TRUE; + } + + /* + * Read the Extended Attributes if present + */ + + for (;;) + { + Status = NtQueryInformationFile(TemplateHandle, + &IoStatusBlock, + &EaInformation, + sizeof(FILE_EA_INFORMATION), + FileEaInformation); + if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0)) + { + EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + EaInformation.EaSize); + if (EaBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + Status = NtQueryEaFile(TemplateHandle, + &IoStatusBlock, + EaBuffer, + EaInformation.EaSize, + FALSE, + NULL, + 0, + NULL, + TRUE); + + if (NT_SUCCESS(Status)) + { + /* we successfully read the extended attributes */ + EaLength = EaInformation.EaSize; + break; + } + else + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + EaBuffer); + EaBuffer = NULL; + + if (Status != STATUS_BUFFER_TOO_SMALL) + { + /* unless we just allocated not enough memory, break the loop + and just continue without copying extended attributes */ + break; + } + } + } + else + { + /* failure or no extended attributes present, break the loop */ + break; + } + } + + if (!NT_SUCCESS(Status)) + { + WARN("Querying the EA data failed: 0x%x\n", Status); + goto Cleanup; + } + + /* + * Create the new directory + */ + + Status = NtCreateFile (&DirectoryHandle, + DesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FileBasicInfo.FileAttributes, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + CreateOptions, + EaBuffer, + EaLength); + if (!NT_SUCCESS(Status)) + { + if (ReparsePoint && + (Status == STATUS_INVALID_PARAMETER || Status == STATUS_ACCESS_DENIED)) + { + /* The FS doesn't seem to support reparse points... */ + WARN("Cannot copy the hardlink, destination doesn\'t support reparse points!\n"); + } + + goto Cleanup; + } + + if (ReparsePoint) + { + /* + * Copy the reparse point + */ + + PREPARSE_GUID_DATA_BUFFER ReparseDataBuffer = + (PREPARSE_GUID_DATA_BUFFER)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + + if (ReparseDataBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + /* query the size of the reparse data buffer structure */ + Status = NtFsControlFile(TemplateHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_GET_REPARSE_POINT, + NULL, + 0, + ReparseDataBuffer, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + if (NT_SUCCESS(Status)) + { + /* write the reparse point */ + Status = NtFsControlFile(DirectoryHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_SET_REPARSE_POINT, + ReparseDataBuffer, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, + NULL, + 0); + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ReparseDataBuffer); + + if (!NT_SUCCESS(Status)) + { + /* fail, we were unable to read the reparse point data! */ + WARN("Querying or setting the reparse point failed: 0x%x\n", Status); + goto Cleanup; + } + } + else + { + /* + * Copy alternate file streams, if existing + */ + + /* FIXME - enumerate and copy the file streams */ + } + + /* + * We successfully created the directory and copied all information + * from the template directory + */ + Status = STATUS_SUCCESS; + +Cleanup: + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtPathU.Buffer); + +CleanupNoNtPath: + if (TemplateHandle != NULL) + { + NtClose(TemplateHandle); + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtTemplatePathU.Buffer); + + /* free the he extended attributes buffer */ + if (EaBuffer != NULL) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + EaBuffer); + } + + if (DirectoryHandle != NULL) + { + NtClose(DirectoryHandle); + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +RemoveDirectoryA ( + LPCSTR lpPathName + ) +{ + PWCHAR PathNameW; + + TRACE("RemoveDirectoryA(%s)\n",lpPathName); + + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; + + return RemoveDirectoryW (PathNameW); +} + + +/* + * @implemented + */ +BOOL +WINAPI +RemoveDirectoryW ( + LPCWSTR lpPathName + ) +{ + FILE_DISPOSITION_INFORMATION FileDispInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE DirectoryHandle = NULL; + NTSTATUS Status; + + TRACE("lpPathName %S\n", lpPathName); + + if (!RtlDosPathNameToNtPathName_U (lpPathName, + &NtPathU, + NULL, + NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + TRACE("NtPathU '%S'\n", NtPathU.Buffer); + + Status = NtOpenFile(&DirectoryHandle, + DELETE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + + RtlFreeUnicodeString(&NtPathU); + + if (!NT_SUCCESS(Status)) + { + WARN("Status 0x%08x\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + FileDispInfo.DeleteFile = TRUE; + + Status = NtSetInformationFile (DirectoryHandle, + &IoStatusBlock, + &FileDispInfo, + sizeof(FILE_DISPOSITION_INFORMATION), + FileDispositionInformation); + NtClose(DirectoryHandle); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetFullPathNameA ( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart + ) +{ + WCHAR BufferW[MAX_PATH]; + PWCHAR FileNameW; + DWORD ret; + LPWSTR FilePartW = NULL; + + TRACE("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, " + "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart); + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return 0; + + ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW); + + if (!ret) + return 0; + + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); + + if (ret < nBufferLength && lpFilePart) + { + /* if the path closed with '\', FilePart is NULL */ + if (!FilePartW) + *lpFilePart=NULL; + else + *lpFilePart = (FilePartW - BufferW) + lpBuffer; + } + + TRACE("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n", + lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart); + + return ret; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetFullPathNameW ( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart + ) +{ + ULONG Length; + + TRACE("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, " + "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart); + + Length = RtlGetFullPathName_U ((LPWSTR)lpFileName, + nBufferLength * sizeof(WCHAR), + lpBuffer, + lpFilePart); + + TRACE("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n", + lpBuffer, (lpFilePart == NULL) ? L"NULL" : *lpFilePart, Length / sizeof(WCHAR)); + + if (!lpFileName) + { +#if (WINVER >= _WIN32_WINNT_WIN7) + SetLastError(ERROR_INVALID_PARAMETER); +#endif + return 0; + } + + return Length/sizeof(WCHAR); +} + + +/* + * NOTE: Copied from Wine. + * @implemented + */ +DWORD +WINAPI +GetShortPathNameA ( + LPCSTR longpath, + LPSTR shortpath, + DWORD shortlen + ) +{ + PWCHAR LongPathW; + WCHAR ShortPathW[MAX_PATH]; + DWORD ret; + + if (!longpath) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!(LongPathW = FilenameA2W(longpath, FALSE))) + return 0; + + ret = GetShortPathNameW(LongPathW, ShortPathW, MAX_PATH); + + if (!ret) + return 0; + + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(shortpath, shortlen, ShortPathW, ret+1); +} + + +/* + * NOTE: Copied from Wine. + * @implemented + */ +DWORD +WINAPI +GetShortPathNameW ( + LPCWSTR longpath, + LPWSTR shortpath, + DWORD shortlen + ) +{ + WCHAR tmpshortpath[MAX_PATH]; + LPCWSTR p; + DWORD sp = 0, lp = 0; + DWORD tmplen; + WIN32_FIND_DATAW wfd; + HANDLE goit; + UNICODE_STRING ustr; + WCHAR ustr_buf[8+1+3+1]; + + TRACE("GetShortPathNameW: %S\n",longpath); + + if (!longpath) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (!longpath[0]) + { + SetLastError(ERROR_BAD_PATHNAME); + return 0; + } + + /* check for drive letter */ + if (longpath[0] != '/' && longpath[1] == ':' ) + { + tmpshortpath[0] = longpath[0]; + tmpshortpath[1] = ':'; + sp = lp = 2; + } + + ustr.Buffer = ustr_buf; + ustr.Length = 0; + ustr.MaximumLength = sizeof(ustr_buf); + + while (longpath[lp]) + { + /* check for path delimiters and reproduce them */ + if (longpath[lp] == '\\' || longpath[lp] == '/') + { + if (!sp || tmpshortpath[sp-1] != '\\') + { + /* strip double "\\" */ + tmpshortpath[sp] = '\\'; + sp++; + } + tmpshortpath[sp] = 0; /* terminate string */ + lp++; + continue; + } + + for (p = longpath + lp; *p && *p != '/' && *p != '\\'; p++); + tmplen = p - (longpath + lp); + lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1); + /* Check, if the current element is a valid dos name */ + if (tmplen <= 8+1+3) + { + BOOLEAN spaces; + memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR)); + ustr_buf[tmplen] = '\0'; + ustr.Length = (USHORT)tmplen * sizeof(WCHAR); + if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, &spaces) && !spaces) + { + sp += tmplen; + lp += tmplen; + continue; + } + } + + /* Check if the file exists and use the existing short file name */ + goit = FindFirstFileW(tmpshortpath, &wfd); + if (goit == INVALID_HANDLE_VALUE) goto notfound; + FindClose(goit); + lstrcpyW(tmpshortpath + sp, wfd.cAlternateFileName); + sp += lstrlenW(tmpshortpath + sp); + lp += tmplen; + } + tmpshortpath[sp] = 0; + + tmplen = lstrlenW(tmpshortpath) + 1; + if (tmplen <= shortlen) + { + lstrcpyW(shortpath, tmpshortpath); + tmplen--; /* length without 0 */ + } + + return tmplen; + + notfound: + SetLastError ( ERROR_FILE_NOT_FOUND ); + return 0; +} + + +/* + * @implemented + */ +DWORD +WINAPI +SearchPathA ( + LPCSTR lpPath, + LPCSTR lpFileName, + LPCSTR lpExtension, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart + ) +{ + UNICODE_STRING PathU = { 0, 0, NULL }; + UNICODE_STRING FileNameU = { 0, 0, NULL }; + UNICODE_STRING ExtensionU = { 0, 0, NULL }; + UNICODE_STRING BufferU = { 0, 0, NULL }; + ANSI_STRING Path; + ANSI_STRING FileName; + ANSI_STRING Extension; + ANSI_STRING Buffer; + PWCHAR FilePartW; + DWORD RetValue = 0; + NTSTATUS Status = STATUS_SUCCESS; + + if (!lpFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + RtlInitAnsiString (&Path, + (LPSTR)lpPath); + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + RtlInitAnsiString (&Extension, + (LPSTR)lpExtension); + + /* convert ansi (or oem) strings to unicode */ + if (bIsFileApiAnsi) + { + Status = RtlAnsiStringToUnicodeString (&PathU, + &Path, + TRUE); + if (!NT_SUCCESS(Status)) + goto Cleanup; + + Status = RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + if (!NT_SUCCESS(Status)) + goto Cleanup; + + Status = RtlAnsiStringToUnicodeString (&ExtensionU, + &Extension, + TRUE); + if (!NT_SUCCESS(Status)) + goto Cleanup; + } + else + { + Status = RtlOemStringToUnicodeString (&PathU, + &Path, + TRUE); + if (!NT_SUCCESS(Status)) + goto Cleanup; + Status = RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + if (!NT_SUCCESS(Status)) + goto Cleanup; + + Status = RtlOemStringToUnicodeString (&ExtensionU, + &Extension, + TRUE); + if (!NT_SUCCESS(Status)) + goto Cleanup; + } + + BufferU.MaximumLength = min(nBufferLength * sizeof(WCHAR), USHRT_MAX); + BufferU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + BufferU.MaximumLength); + if (BufferU.Buffer == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + Buffer.MaximumLength = min(nBufferLength, USHRT_MAX); + Buffer.Buffer = lpBuffer; + + RetValue = SearchPathW (NULL == lpPath ? NULL : PathU.Buffer, + NULL == lpFileName ? NULL : FileNameU.Buffer, + NULL == lpExtension ? NULL : ExtensionU.Buffer, + nBufferLength, + BufferU.Buffer, + &FilePartW); + + if (0 != RetValue) + { + BufferU.Length = wcslen(BufferU.Buffer) * sizeof(WCHAR); + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + Status = RtlUnicodeStringToAnsiString(&Buffer, + &BufferU, + FALSE); + else + Status = RtlUnicodeStringToOemString(&Buffer, + &BufferU, + FALSE); + + if (NT_SUCCESS(Status) && Buffer.Buffer) + { + /* nul-terminate ascii string */ + Buffer.Buffer[BufferU.Length / sizeof(WCHAR)] = '\0'; + + if (NULL != lpFilePart && BufferU.Length != 0) + { + *lpFilePart = strrchr (lpBuffer, '\\') + 1; + } + } + } + +Cleanup: + RtlFreeHeap (RtlGetProcessHeap (), + 0, + PathU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + ExtensionU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + BufferU.Buffer); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return RetValue; +} + + +/*********************************************************************** + * ContainsPath (Wine name: contains_pathW) + * + * Check if the file name contains a path; helper for SearchPathW. + * A relative path is not considered a path unless it starts with ./ or ../ + */ +static +BOOL +ContainsPath(LPCWSTR name) +{ + if (RtlDetermineDosPathNameType_U(name) != RtlPathTypeRelative) return TRUE; + if (name[0] != '.') return FALSE; + if (name[1] == '/' || name[1] == '\\' || name[1] == '\0') return TRUE; + return (name[1] == '.' && (name[2] == '/' || name[2] == '\\')); +} + + +/* + * @implemented + */ +DWORD +WINAPI +SearchPathW(LPCWSTR lpPath, + LPCWSTR lpFileName, + LPCWSTR lpExtension, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart) +{ + DWORD ret = 0; + + if (!lpFileName || !lpFileName[0]) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + /* If the name contains an explicit path, ignore the path */ + if (ContainsPath(lpFileName)) + { + /* try first without extension */ + if (RtlDoesFileExists_U(lpFileName)) + return GetFullPathNameW(lpFileName, nBufferLength, lpBuffer, lpFilePart); + + if (lpExtension) + { + LPCWSTR p = wcsrchr(lpFileName, '.'); + if (p && !strchr((const char *)p, '/') && !wcschr( p, '\\' )) + lpExtension = NULL; /* Ignore the specified extension */ + } + + /* Allocate a buffer for the file name and extension */ + if (lpExtension) + { + LPWSTR tmp; + DWORD len = wcslen(lpFileName) + wcslen(lpExtension); + + if (!(tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)))) + { + SetLastError(ERROR_OUTOFMEMORY); + return 0; + } + wcscpy(tmp, lpFileName); + wcscat(tmp, lpExtension); + if (RtlDoesFileExists_U(tmp)) + ret = GetFullPathNameW(tmp, nBufferLength, lpBuffer, lpFilePart); + RtlFreeHeap(RtlGetProcessHeap(), 0, tmp); + } + } + else if (lpPath && lpPath[0]) /* search in the specified path */ + { + ret = RtlDosSearchPath_U(lpPath, + lpFileName, + lpExtension, + nBufferLength * sizeof(WCHAR), + lpBuffer, + lpFilePart) / sizeof(WCHAR); + } + else /* search in the default path */ + { + WCHAR *DllPath = GetDllLoadPath(NULL); + + if (DllPath) + { + ret = RtlDosSearchPath_U(DllPath, + lpFileName, + lpExtension, + nBufferLength * sizeof(WCHAR), + lpBuffer, + lpFilePart) / sizeof(WCHAR); + RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath); + } + else + { + SetLastError(ERROR_OUTOFMEMORY); + return 0; + } + } + + if (!ret) SetLastError(ERROR_FILE_NOT_FOUND); + + return ret; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetDllDirectoryW( + LPCWSTR lpPathName + ) +{ + UNICODE_STRING PathName; + + RtlInitUnicodeString(&PathName, lpPathName); + + RtlEnterCriticalSection(&BaseDllDirectoryLock); + if(PathName.Length > 0) + { + if(PathName.Length + sizeof(WCHAR) <= BaseDllDirectory.MaximumLength) + { + RtlCopyUnicodeString(&BaseDllDirectory, &PathName); + } + else + { + RtlFreeUnicodeString(&BaseDllDirectory); + if(!(BaseDllDirectory.Buffer = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + PathName.Length + sizeof(WCHAR)))) + { + RtlLeaveCriticalSection(&BaseDllDirectoryLock); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + BaseDllDirectory.Length = 0; + BaseDllDirectory.MaximumLength = PathName.Length + sizeof(WCHAR); + + RtlCopyUnicodeString(&BaseDllDirectory, &PathName); + } + } + else + { + RtlFreeUnicodeString(&BaseDllDirectory); + } + RtlLeaveCriticalSection(&BaseDllDirectoryLock); + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetDllDirectoryA( + LPCSTR lpPathName /* can be NULL */ + ) +{ + PWCHAR PathNameW=NULL; + + if(lpPathName) + { + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; + } + + return SetDllDirectoryW(PathNameW); +} + +/* + * @implemented + */ +DWORD +WINAPI +GetDllDirectoryW( + DWORD nBufferLength, + LPWSTR lpBuffer + ) +{ + DWORD Ret; + + RtlEnterCriticalSection(&BaseDllDirectoryLock); + if(nBufferLength > 0) + { + Ret = BaseDllDirectory.Length / sizeof(WCHAR); + if(Ret > nBufferLength - 1) + { + Ret = nBufferLength - 1; + } + + if(Ret > 0) + { + RtlCopyMemory(lpBuffer, BaseDllDirectory.Buffer, Ret * sizeof(WCHAR)); + } + lpBuffer[Ret] = L'\0'; + } + else + { + /* include termination character, even if the string is empty! */ + Ret = (BaseDllDirectory.Length / sizeof(WCHAR)) + 1; + } + RtlLeaveCriticalSection(&BaseDllDirectoryLock); + + return Ret; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetDllDirectoryA( + DWORD nBufferLength, + LPSTR lpBuffer + ) +{ + WCHAR BufferW[MAX_PATH]; + DWORD ret; + + ret = GetDllDirectoryW(MAX_PATH, BufferW); + + if (!ret) + return 0; + + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); +} + + +/* + * @implemented + */ +BOOL WINAPI +NeedCurrentDirectoryForExePathW(LPCWSTR ExeName) +{ + static const WCHAR env_name[] = {'N','o','D','e','f','a','u','l','t', + 'C','u','r','r','e','n','t', + 'D','i','r','e','c','t','o','r','y', + 'I','n','E','x','e','P','a','t','h',0}; + WCHAR env_val; + + /* MSDN mentions some 'registry location'. We do not use registry. */ + FIXME("(%s): partial stub\n", debugstr_w(ExeName)); + + if (wcschr(ExeName, L'\\')) + return TRUE; + + /* Check the existence of the variable, not value */ + if (!GetEnvironmentVariableW( env_name, &env_val, 1 )) + return TRUE; + + return FALSE; +} + + +/* + * @implemented + */ +BOOL WINAPI +NeedCurrentDirectoryForExePathA(LPCSTR ExeName) +{ + WCHAR *ExeNameW; + + if (!(ExeNameW = FilenameA2W(ExeName, FALSE))) + return TRUE; + + return NeedCurrentDirectoryForExePathW(ExeNameW); +} + + + + + +/*********************************************************************** + * @implemented + * + * GetLongPathNameW (KERNEL32.@) + * + * NOTES + * observed (Win2000): + * shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0 + * shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0 + */ +DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen ) +{ +#define MAX_PATHNAME_LEN 1024 + + WCHAR tmplongpath[MAX_PATHNAME_LEN]; + LPCWSTR p; + DWORD sp = 0, lp = 0; + DWORD tmplen; + BOOL unixabsolute; + WIN32_FIND_DATAW wfd; + HANDLE goit; + + if (!shortpath) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (!shortpath[0]) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return 0; + } + + TRACE("GetLongPathNameW(%s,%p,%ld)\n", shortpath, longpath, longlen); + + if (shortpath[0] == '\\' && shortpath[1] == '\\') + { + WARN("ERR: UNC pathname %s\n", shortpath); + lstrcpynW( longpath, shortpath, longlen ); + return wcslen(longpath); + } + unixabsolute = (shortpath[0] == '/'); + /* check for drive letter */ + if (!unixabsolute && shortpath[1] == ':' ) + { + tmplongpath[0] = shortpath[0]; + tmplongpath[1] = ':'; + lp = sp = 2; + } + + while (shortpath[sp]) + { + /* check for path delimiters and reproduce them */ + if (shortpath[sp] == '\\' || shortpath[sp] == '/') + { + if (!lp || tmplongpath[lp-1] != '\\') + { + /* strip double "\\" */ + tmplongpath[lp++] = '\\'; + } + tmplongpath[lp] = 0; /* terminate string */ + sp++; + continue; + } + + p = shortpath + sp; + if (sp == 0 && p[0] == '.' && (p[1] == '/' || p[1] == '\\')) + { + tmplongpath[lp++] = *p++; + tmplongpath[lp++] = *p++; + } + for (; *p && *p != '/' && *p != '\\'; p++); + tmplen = p - (shortpath + sp); + lstrcpynW(tmplongpath + lp, shortpath + sp, tmplen + 1); + /* Check if the file exists and use the existing file name */ + goit = FindFirstFileW(tmplongpath, &wfd); + if (goit == INVALID_HANDLE_VALUE) + { + TRACE("not found %s!\n", tmplongpath); + SetLastError ( ERROR_FILE_NOT_FOUND ); + return 0; + } + FindClose(goit); + wcscpy(tmplongpath + lp, wfd.cFileName); + lp += wcslen(tmplongpath + lp); + sp += tmplen; + } + tmplen = wcslen(shortpath) - 1; + if ((shortpath[tmplen] == '/' || shortpath[tmplen] == '\\') && + (tmplongpath[lp - 1] != '/' && tmplongpath[lp - 1] != '\\')) + tmplongpath[lp++] = shortpath[tmplen]; + tmplongpath[lp] = 0; + + tmplen = wcslen(tmplongpath) + 1; + if (tmplen <= longlen) + { + wcscpy(longpath, tmplongpath); + TRACE("returning %s\n", longpath); + tmplen--; /* length without 0 */ + } + + return tmplen; +} + + + +/*********************************************************************** + * GetLongPathNameA (KERNEL32.@) + */ +DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen ) +{ + WCHAR *shortpathW; + WCHAR longpathW[MAX_PATH]; + DWORD ret; + + TRACE("GetLongPathNameA %s, %i\n",shortpath,longlen ); + + if (!(shortpathW = FilenameA2W( shortpath, FALSE ))) + return 0; + + ret = GetLongPathNameW(shortpathW, longpathW, MAX_PATH); + + if (!ret) return 0; + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(longpath, longlen, longpathW, ret+1 ); +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/dosdev.c b/dll/win32/kernel32/client/file/dosdev.c new file mode 100644 index 00000000000..33ea76b6807 --- /dev/null +++ b/dll/win32/kernel32/client/file/dosdev.c @@ -0,0 +1,490 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/dosdev.c + * PURPOSE: Dos device functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include +#include +DEBUG_CHANNEL(kernel32file); + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +DefineDosDeviceA( + DWORD dwFlags, + LPCSTR lpDeviceName, + LPCSTR lpTargetPath + ) +{ + UNICODE_STRING DeviceNameU = {0}; + UNICODE_STRING TargetPathU = {0}; + BOOL Result; + + if (lpDeviceName && + ! RtlCreateUnicodeStringFromAsciiz(&DeviceNameU, + (LPSTR)lpDeviceName)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + if (lpTargetPath && + ! RtlCreateUnicodeStringFromAsciiz(&TargetPathU, + (LPSTR)lpTargetPath)) + { + if (DeviceNameU.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap (), + 0, + DeviceNameU.Buffer); + } + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Result = DefineDosDeviceW(dwFlags, + DeviceNameU.Buffer, + TargetPathU.Buffer); + + if (TargetPathU.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap (), + 0, + TargetPathU.Buffer); + } + + if (DeviceNameU.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap (), + 0, + DeviceNameU.Buffer); + } + return Result; +} + + +/* + * @implemented + */ +BOOL +WINAPI +DefineDosDeviceW( + DWORD dwFlags, + LPCWSTR lpDeviceName, + LPCWSTR lpTargetPath + ) +{ + ULONG ArgumentCount; + ULONG BufferSize; + PCSR_CAPTURE_BUFFER CaptureBuffer; + CSR_API_MESSAGE Request; + NTSTATUS Status; + UNICODE_STRING NtTargetPathU; + UNICODE_STRING DeviceNameU; + UNICODE_STRING DeviceUpcaseNameU; + HANDLE hUser32; + DEV_BROADCAST_VOLUME dbcv; + BOOL Result = TRUE; + DWORD dwRecipients; + typedef long (WINAPI *BSM_type)(DWORD,LPDWORD,UINT,WPARAM,LPARAM); + BSM_type BSM_ptr; + + if ( (dwFlags & 0xFFFFFFF0) || + ((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) && + ! (dwFlags & DDD_REMOVE_DEFINITION)) ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ArgumentCount = 1; + BufferSize = 0; + if (! lpTargetPath) + { + RtlInitUnicodeString(&NtTargetPathU, + NULL); + } + else + { + if (dwFlags & DDD_RAW_TARGET_PATH) + { + RtlInitUnicodeString(&NtTargetPathU, + lpTargetPath); + } + else + { + if (! RtlDosPathNameToNtPathName_U(lpTargetPath, + &NtTargetPathU, + 0, + 0)) + { + WARN("RtlDosPathNameToNtPathName_U() failed\n"); + BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID); + return FALSE; + } + } + ArgumentCount = 2; + BufferSize += NtTargetPathU.Length; + } + + RtlInitUnicodeString(&DeviceNameU, + lpDeviceName); + RtlUpcaseUnicodeString(&DeviceUpcaseNameU, + &DeviceNameU, + TRUE); + BufferSize += DeviceUpcaseNameU.Length; + + CaptureBuffer = CsrAllocateCaptureBuffer(ArgumentCount, + BufferSize); + if (! CaptureBuffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + Result = FALSE; + } + else + { + Request.Data.DefineDosDeviceRequest.dwFlags = dwFlags; + + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)DeviceUpcaseNameU.Buffer, + DeviceUpcaseNameU.Length, + (PVOID*)&Request.Data.DefineDosDeviceRequest.DeviceName.Buffer); + + Request.Data.DefineDosDeviceRequest.DeviceName.Length = + DeviceUpcaseNameU.Length; + Request.Data.DefineDosDeviceRequest.DeviceName.MaximumLength = + DeviceUpcaseNameU.Length; + + if (NtTargetPathU.Buffer) + { + CsrCaptureMessageBuffer(CaptureBuffer, + (PVOID)NtTargetPathU.Buffer, + NtTargetPathU.Length, + (PVOID*)&Request.Data.DefineDosDeviceRequest.TargetName.Buffer); + } + Request.Data.DefineDosDeviceRequest.TargetName.Length = + NtTargetPathU.Length; + Request.Data.DefineDosDeviceRequest.TargetName.MaximumLength = + NtTargetPathU.Length; + + Status = CsrClientCallServer(&Request, + CaptureBuffer, + MAKE_CSR_API(DEFINE_DOS_DEVICE, CSR_CONSOLE), + sizeof(CSR_API_MESSAGE)); + CsrFreeCaptureBuffer(CaptureBuffer); + + if (! NT_SUCCESS(Status) || + ! NT_SUCCESS(Status = Request.Status)) + { + WARN("CsrClientCallServer() failed (Status %lx)\n", + Status); + BaseSetLastNTError(Status); + Result = FALSE; + } + else + { + if (! (dwFlags & DDD_NO_BROADCAST_SYSTEM) && + DeviceUpcaseNameU.Length == 2 * sizeof(WCHAR) && + DeviceUpcaseNameU.Buffer[1] == L':' && + ( (DeviceUpcaseNameU.Buffer[0] - L'A') < 26 )) + { + hUser32 = LoadLibraryA("user32.dll"); + if (hUser32) + { + BSM_ptr = (BSM_type) + GetProcAddress(hUser32, "BroadcastSystemMessageW"); + if (BSM_ptr) + { + dwRecipients = BSM_APPLICATIONS; + dbcv.dbcv_size = sizeof(DEV_BROADCAST_VOLUME); + dbcv.dbcv_devicetype = DBT_DEVTYP_VOLUME; + dbcv.dbcv_reserved = 0; + dbcv.dbcv_unitmask |= + (1 << (DeviceUpcaseNameU.Buffer[0] - L'A')); + dbcv.dbcv_flags = DBTF_NET; + (void) BSM_ptr(BSF_SENDNOTIFYMESSAGE | BSF_FLUSHDISK, + &dwRecipients, + WM_DEVICECHANGE, + (WPARAM)DBT_DEVICEARRIVAL, + (LPARAM)&dbcv); + } + FreeLibrary(hUser32); + } + } + } + } + + if (NtTargetPathU.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtTargetPathU.Buffer); + } + RtlFreeUnicodeString(&DeviceUpcaseNameU); + return Result; +} + + +/* + * @implemented + */ +DWORD +WINAPI +QueryDosDeviceA( + LPCSTR lpDeviceName, + LPSTR lpTargetPath, + DWORD ucchMax + ) +{ + UNICODE_STRING DeviceNameU; + UNICODE_STRING TargetPathU; + ANSI_STRING TargetPathA; + DWORD Length; + DWORD CurrentLength; + PWCHAR Buffer; + + if (lpDeviceName) + { + if (!RtlCreateUnicodeStringFromAsciiz (&DeviceNameU, + (LPSTR)lpDeviceName)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + ucchMax * sizeof(WCHAR)); + if (Buffer == NULL) + { + if (lpDeviceName) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DeviceNameU.Buffer); + } + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Length = QueryDosDeviceW (lpDeviceName ? DeviceNameU.Buffer : NULL, + Buffer, + ucchMax); + if (Length != 0) + { + TargetPathA.Buffer = lpTargetPath; + TargetPathU.Buffer = Buffer; + ucchMax = Length; + + while (ucchMax) + { + CurrentLength = min (ucchMax, MAXUSHORT / 2); + TargetPathU.MaximumLength = TargetPathU.Length = (USHORT)CurrentLength * sizeof(WCHAR); + + TargetPathA.Length = 0; + TargetPathA.MaximumLength = (USHORT)CurrentLength; + + RtlUnicodeStringToAnsiString (&TargetPathA, + &TargetPathU, + FALSE); + ucchMax -= CurrentLength; + TargetPathA.Buffer += TargetPathA.Length; + TargetPathU.Buffer += TargetPathU.Length / sizeof(WCHAR); + } + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + Buffer); + if (lpDeviceName) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DeviceNameU.Buffer); + } + return Length; +} + + +/* + * @implemented + */ +DWORD +WINAPI +QueryDosDeviceW( + LPCWSTR lpDeviceName, + LPWSTR lpTargetPath, + DWORD ucchMax + ) +{ + POBJECT_DIRECTORY_INFORMATION DirInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeString; + HANDLE DirectoryHandle; + HANDLE DeviceHandle; + ULONG ReturnLength; + ULONG NameLength; + ULONG Length; + ULONG Context; + BOOLEAN RestartScan; + NTSTATUS Status; + UCHAR Buffer[512]; + PWSTR Ptr; + + /* Open the '\??' directory */ + RtlInitUnicodeString (&UnicodeString, + L"\\??"); + InitializeObjectAttributes (&ObjectAttributes, + &UnicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenDirectoryObject (&DirectoryHandle, + DIRECTORY_QUERY, + &ObjectAttributes); + if (!NT_SUCCESS (Status)) + { + WARN ("NtOpenDirectoryObject() failed (Status %lx)\n", Status); + BaseSetLastNTError (Status); + return 0; + } + + Length = 0; + + if (lpDeviceName != NULL) + { + /* Open the lpDeviceName link object */ + RtlInitUnicodeString (&UnicodeString, + (PWSTR)lpDeviceName); + InitializeObjectAttributes (&ObjectAttributes, + &UnicodeString, + OBJ_CASE_INSENSITIVE, + DirectoryHandle, + NULL); + Status = NtOpenSymbolicLinkObject (&DeviceHandle, + SYMBOLIC_LINK_QUERY, + &ObjectAttributes); + if (!NT_SUCCESS (Status)) + { + WARN ("NtOpenSymbolicLinkObject() failed (Status %lx)\n", Status); + NtClose (DirectoryHandle); + BaseSetLastNTError (Status); + return 0; + } + + /* Query link target */ + UnicodeString.Length = 0; + UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR); + UnicodeString.Buffer = lpTargetPath; + + ReturnLength = 0; + Status = NtQuerySymbolicLinkObject (DeviceHandle, + &UnicodeString, + &ReturnLength); + NtClose (DeviceHandle); + NtClose (DirectoryHandle); + if (!NT_SUCCESS (Status)) + { + WARN ("NtQuerySymbolicLinkObject() failed (Status %lx)\n", Status); + BaseSetLastNTError (Status); + return 0; + } + + TRACE ("ReturnLength: %lu\n", ReturnLength); + TRACE ("TargetLength: %hu\n", UnicodeString.Length); + TRACE ("Target: '%wZ'\n", &UnicodeString); + + Length = UnicodeString.Length / sizeof(WCHAR); + if (Length < ucchMax) + { + /* Append null-charcter */ + lpTargetPath[Length] = UNICODE_NULL; + Length++; + } + else + { + TRACE ("Buffer is too small\n"); + BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL); + return 0; + } + } + else + { + RestartScan = TRUE; + Context = 0; + Ptr = lpTargetPath; + DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer; + + while (TRUE) + { + Status = NtQueryDirectoryObject (DirectoryHandle, + Buffer, + sizeof (Buffer), + TRUE, + RestartScan, + &Context, + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_NO_MORE_ENTRIES) + { + /* Terminate the buffer */ + *Ptr = UNICODE_NULL; + Length++; + + Status = STATUS_SUCCESS; + } + else + { + Length = 0; + } + BaseSetLastNTError (Status); + break; + } + + if (!wcscmp (DirInfo->TypeName.Buffer, L"SymbolicLink")) + { + TRACE ("Name: '%wZ'\n", &DirInfo->Name); + + NameLength = DirInfo->Name.Length / sizeof(WCHAR); + if (Length + NameLength + 1 >= ucchMax) + { + Length = 0; + BaseSetLastNTError (STATUS_BUFFER_TOO_SMALL); + break; + } + + memcpy (Ptr, + DirInfo->Name.Buffer, + DirInfo->Name.Length); + Ptr += NameLength; + Length += NameLength; + *Ptr = UNICODE_NULL; + Ptr++; + Length++; + } + + RestartScan = FALSE; + } + + NtClose (DirectoryHandle); + } + + return Length; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/file.c b/dll/win32/kernel32/client/file/file.c new file mode 100644 index 00000000000..2aa0dc134fb --- /dev/null +++ b/dll/win32/kernel32/client/file/file.c @@ -0,0 +1,2162 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/file.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Pierre Schweitzer (pierre.schweitzer@reactos.org) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* GLOBALS ******************************************************************/ + +BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem + +/* FUNCTIONS ****************************************************************/ + + + +PWCHAR +FilenameA2W(LPCSTR NameA, BOOL alloc) +{ + ANSI_STRING str; + UNICODE_STRING strW; + PUNICODE_STRING pstrW; + NTSTATUS Status; + + //ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer); + ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer)); + + RtlInitAnsiString(&str, NameA); + pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString; + + if (bIsFileApiAnsi) + Status= RtlAnsiStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc ); + else + Status= RtlOemStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc ); + + if (NT_SUCCESS(Status)) + return pstrW->Buffer; + + if (Status== STATUS_BUFFER_OVERFLOW) + SetLastError( ERROR_FILENAME_EXCED_RANGE ); + else + BaseSetLastNTError(Status); + + return NULL; +} + + +/* +No copy/conversion is done if the dest. buffer is too small. + +Returns: + Success: number of TCHARS copied into dest. buffer NOT including nullterm + Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm +*/ +DWORD +FilenameU2A_FitOrFail( + LPSTR DestA, + INT destLen, /* buffer size in TCHARS incl. nullchar */ + PUNICODE_STRING SourceU + ) +{ + DWORD ret; + + /* destLen should never exceed MAX_PATH */ + if (destLen > MAX_PATH) destLen = MAX_PATH; + + ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU); + /* ret incl. nullchar */ + + if (DestA && (INT)ret <= destLen) + { + ANSI_STRING str; + + str.Buffer = DestA; + str.MaximumLength = (USHORT)destLen; + + + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString(&str, SourceU, FALSE ); + else + RtlUnicodeStringToOemString(&str, SourceU, FALSE ); + + ret = str.Length; /* SUCCESS: length without terminating 0 */ + } + + return ret; +} + + +/* +No copy/conversion is done if the dest. buffer is too small. + +Returns: + Success: number of TCHARS copied into dest. buffer NOT including nullterm + Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm +*/ +DWORD +FilenameW2A_FitOrFail( + LPSTR DestA, + INT destLen, /* buffer size in TCHARS incl. nullchar */ + LPCWSTR SourceW, + INT sourceLen /* buffer size in TCHARS incl. nullchar */ + ) +{ + UNICODE_STRING strW; + + if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1; + + strW.Buffer = (PWCHAR)SourceW; + strW.MaximumLength = sourceLen * sizeof(WCHAR); + strW.Length = strW.MaximumLength - sizeof(WCHAR); + + return FilenameU2A_FitOrFail(DestA, destLen, &strW); +} + + +/* +Return: num. TCHARS copied into dest including nullterm +*/ +DWORD +FilenameA2W_N( + LPWSTR dest, + INT destlen, /* buffer size in TCHARS incl. nullchar */ + LPCSTR src, + INT srclen /* buffer size in TCHARS incl. nullchar */ + ) +{ + DWORD ret; + + if (srclen < 0) srclen = strlen( src ) + 1; + + if (bIsFileApiAnsi) + RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen ); + else + RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen ); + + if (ret) dest[(ret/sizeof(WCHAR))-1]=0; + + return ret/sizeof(WCHAR); +} + +/* +Return: num. TCHARS copied into dest including nullterm +*/ +DWORD +FilenameW2A_N( + LPSTR dest, + INT destlen, /* buffer size in TCHARS incl. nullchar */ + LPCWSTR src, + INT srclen /* buffer size in TCHARS incl. nullchar */ + ) +{ + DWORD ret; + + if (srclen < 0) srclen = wcslen( src ) + 1; + + if (bIsFileApiAnsi) + RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR)); + else + RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) ); + + if (ret) dest[ret-1]=0; + + return ret; +} + + +/* + * @implemented + */ +VOID +WINAPI +SetFileApisToOEM(VOID) +{ + /* Set the correct Base Api */ + Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString; + + /* FIXME: Old, deprecated way */ + bIsFileApiAnsi = FALSE; +} + + +/* + * @implemented + */ +VOID +WINAPI +SetFileApisToANSI(VOID) +{ + /* Set the correct Base Api */ + Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString; + + /* FIXME: Old, deprecated way */ + bIsFileApiAnsi = TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +AreFileApisANSI(VOID) +{ + return bIsFileApiAnsi; +} + + +/* + * @implemented + */ +HFILE WINAPI +OpenFile(LPCSTR lpFileName, + LPOFSTRUCT lpReOpenBuff, + UINT uStyle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING FileNameString; + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + WCHAR PathNameW[MAX_PATH]; + HANDLE FileHandle = NULL; + NTSTATUS errCode; + PWCHAR FilePart; + ULONG Len; + + TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle); + + if (lpReOpenBuff == NULL) + { + return HFILE_ERROR; + } + + lpReOpenBuff->nErrCode = 0; + + if (uStyle & OF_REOPEN) lpFileName = lpReOpenBuff->szPathName; + + if (!lpFileName) + { + return HFILE_ERROR; + } + + if (!GetFullPathNameA(lpFileName, + sizeof(lpReOpenBuff->szPathName), + lpReOpenBuff->szPathName, + NULL)) + { + lpReOpenBuff->nErrCode = GetLastError(); + return HFILE_ERROR; + } + + if (uStyle & OF_PARSE) + { + lpReOpenBuff->fFixedDisk = (GetDriveTypeA(lpReOpenBuff->szPathName) != DRIVE_REMOVABLE); + TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName, lpReOpenBuff->szPathName); + return 0; + } + + if ((uStyle & OF_EXIST) && !(uStyle & OF_CREATE)) + { + DWORD dwAttributes = GetFileAttributesA(lpReOpenBuff->szPathName); + + switch (dwAttributes) + { + case 0xFFFFFFFF: /* File does not exist */ + SetLastError(ERROR_FILE_NOT_FOUND); + lpReOpenBuff->nErrCode = (WORD) ERROR_FILE_NOT_FOUND; + return -1; + + case FILE_ATTRIBUTE_DIRECTORY: + SetLastError(ERROR_ACCESS_DENIED); + lpReOpenBuff->nErrCode = (WORD) ERROR_ACCESS_DENIED; + return -1; + + default: + lpReOpenBuff->cBytes = sizeof(OFSTRUCT); + return 1; + } + } + lpReOpenBuff->cBytes = sizeof(OFSTRUCT); + if ((uStyle & OF_CREATE) == OF_CREATE) + { + DWORD Sharing; + switch (uStyle & 0x70) + { + case OF_SHARE_EXCLUSIVE: Sharing = 0; break; + case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break; + case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break; + case OF_SHARE_DENY_NONE: + case OF_SHARE_COMPAT: + default: + Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + return (HFILE) CreateFileA (lpFileName, + GENERIC_READ | GENERIC_WRITE, + Sharing, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + 0); + } + + RtlInitAnsiString (&FileName, (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE); + + Len = SearchPathW (NULL, + FileNameU.Buffer, + NULL, + OFS_MAXPATHNAME, + PathNameW, + &FilePart); + + RtlFreeUnicodeString(&FileNameU); + + if (Len == 0 || Len > OFS_MAXPATHNAME) + { + lpReOpenBuff->nErrCode = GetLastError(); + return (HFILE)INVALID_HANDLE_VALUE; + } + + if (uStyle & OF_DELETE) + { + if (!DeleteFileW(PathNameW)) + { + lpReOpenBuff->nErrCode = GetLastError(); + return HFILE_ERROR; + } + TRACE("(%s): OF_DELETE return = OK\n", lpFileName); + return TRUE; + } + + FileName.Buffer = lpReOpenBuff->szPathName; + FileName.Length = 0; + FileName.MaximumLength = OFS_MAXPATHNAME; + + RtlInitUnicodeString(&FileNameU, PathNameW); + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE); + else + RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE); + + if (!RtlDosPathNameToNtPathName_U (PathNameW, + &FileNameString, + NULL, + NULL)) + { + return (HFILE)INVALID_HANDLE_VALUE; + } + + // FILE_SHARE_READ + // FILE_NO_INTERMEDIATE_BUFFERING + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &FileNameString; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + errCode = NtOpenFile (&FileHandle, + GENERIC_READ|SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT); + + RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer); + + lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode); + + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError (errCode); + return (HFILE)INVALID_HANDLE_VALUE; + } + + if (uStyle & OF_EXIST) + { + NtClose(FileHandle); + return (HFILE)1; + } + + return (HFILE)FileHandle; +} + + +/* + * @implemented + */ +BOOL WINAPI +FlushFileBuffers(IN HANDLE hFile) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + + hFile = TranslateStdHandle(hFile); + + if (IsConsoleHandle(hFile)) + { + return FlushConsoleInputBuffer(hFile); + } + + Status = NtFlushBuffersFile(hFile, + &IoStatusBlock); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + return TRUE; +} + + +/* + * @implemented + */ +DWORD WINAPI +SetFilePointer(HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod) +{ + FILE_POSITION_INFORMATION FilePosition; + FILE_STANDARD_INFORMATION FileStandard; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + LARGE_INTEGER Distance; + + TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n", + hFile,lDistanceToMove,dwMoveMethod); + + if(IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return INVALID_SET_FILE_POINTER; + } + + if (lpDistanceToMoveHigh) + { + Distance.u.HighPart = *lpDistanceToMoveHigh; + Distance.u.LowPart = lDistanceToMove; + } + else + { + Distance.QuadPart = lDistanceToMove; + } + + switch(dwMoveMethod) + { + case FILE_CURRENT: + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart; + if (!NT_SUCCESS(errCode)) + { + if (lpDistanceToMoveHigh != NULL) + *lpDistanceToMoveHigh = -1; + BaseSetLastNTError(errCode); + return INVALID_SET_FILE_POINTER; + } + break; + case FILE_END: + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + FilePosition.CurrentByteOffset.QuadPart = + FileStandard.EndOfFile.QuadPart + Distance.QuadPart; + if (!NT_SUCCESS(errCode)) + { + if (lpDistanceToMoveHigh != NULL) + *lpDistanceToMoveHigh = -1; + BaseSetLastNTError(errCode); + return INVALID_SET_FILE_POINTER; + } + break; + case FILE_BEGIN: + FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart; + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_SET_FILE_POINTER; + } + + if(FilePosition.CurrentByteOffset.QuadPart < 0) + { + SetLastError(ERROR_NEGATIVE_SEEK); + return INVALID_SET_FILE_POINTER; + } + + if (lpDistanceToMoveHigh == NULL && FilePosition.CurrentByteOffset.HighPart != 0) + { + /* If we're moving the pointer outside of the 32 bit boundaries but + the application only passed a 32 bit value we need to bail out! */ + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_SET_FILE_POINTER; + } + + errCode = NtSetInformationFile(hFile, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (!NT_SUCCESS(errCode)) + { + if (lpDistanceToMoveHigh != NULL) + *lpDistanceToMoveHigh = -1; + + BaseSetLastNTError(errCode); + return INVALID_SET_FILE_POINTER; + } + + if (lpDistanceToMoveHigh != NULL) + { + *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart; + } + + if (FilePosition.CurrentByteOffset.u.LowPart == MAXDWORD) + { + /* The value of -1 is valid here, especially when the new + file position is greater than 4 GB. Since NtSetInformationFile + succeeded we never set an error code and we explicitly need + to clear a previously set error code in this case, which + an application will check if INVALID_SET_FILE_POINTER is returned! */ + SetLastError(ERROR_SUCCESS); + } + + return FilePosition.CurrentByteOffset.u.LowPart; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetFilePointerEx(HANDLE hFile, + LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, + DWORD dwMoveMethod) +{ + FILE_POSITION_INFORMATION FilePosition; + FILE_STANDARD_INFORMATION FileStandard; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + + if(IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + switch(dwMoveMethod) + { + case FILE_CURRENT: + NtQueryInformationFile(hFile, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart; + break; + case FILE_END: + NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + FilePosition.CurrentByteOffset.QuadPart = + FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart; + break; + case FILE_BEGIN: + FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart; + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(FilePosition.CurrentByteOffset.QuadPart < 0) + { + SetLastError(ERROR_NEGATIVE_SEEK); + return FALSE; + } + + errCode = NtSetInformationFile(hFile, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + if (lpNewFilePointer) + { + *lpNewFilePointer = FilePosition.CurrentByteOffset; + } + return TRUE; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetFileType(HANDLE hFile) +{ + FILE_FS_DEVICE_INFORMATION DeviceInfo; + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + /* Get real handle */ + hFile = TranslateStdHandle(hFile); + + /* Check for console handle */ + if (IsConsoleHandle(hFile)) + { + if (VerifyConsoleIoHandle(hFile)) + return FILE_TYPE_CHAR; + } + + Status = NtQueryVolumeInformationFile(hFile, + &StatusBlock, + &DeviceInfo, + sizeof(FILE_FS_DEVICE_INFORMATION), + FileFsDeviceInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FILE_TYPE_UNKNOWN; + } + + switch (DeviceInfo.DeviceType) + { + case FILE_DEVICE_CD_ROM: + case FILE_DEVICE_CD_ROM_FILE_SYSTEM: + case FILE_DEVICE_CONTROLLER: + case FILE_DEVICE_DATALINK: + case FILE_DEVICE_DFS: + case FILE_DEVICE_DISK: + case FILE_DEVICE_DISK_FILE_SYSTEM: + case FILE_DEVICE_VIRTUAL_DISK: + return FILE_TYPE_DISK; + + case FILE_DEVICE_KEYBOARD: + case FILE_DEVICE_MOUSE: + case FILE_DEVICE_NULL: + case FILE_DEVICE_PARALLEL_PORT: + case FILE_DEVICE_PRINTER: + case FILE_DEVICE_SERIAL_PORT: + case FILE_DEVICE_SCREEN: + case FILE_DEVICE_SOUND: + case FILE_DEVICE_MODEM: + return FILE_TYPE_CHAR; + + case FILE_DEVICE_NAMED_PIPE: + return FILE_TYPE_PIPE; + } + + return FILE_TYPE_UNKNOWN; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetFileSize(HANDLE hFile, + LPDWORD lpFileSizeHigh) +{ + NTSTATUS errCode; + FILE_STANDARD_INFORMATION FileStandard; + IO_STATUS_BLOCK IoStatusBlock; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + if ( lpFileSizeHigh == NULL ) + { + return -1; + } + else + { + return 0; + } + } + if ( lpFileSizeHigh != NULL ) + *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart; + + return FileStandard.EndOfFile.u.LowPart; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetFileSizeEx( + HANDLE hFile, + PLARGE_INTEGER lpFileSize + ) +{ + NTSTATUS errCode; + FILE_STANDARD_INFORMATION FileStandard; + IO_STATUS_BLOCK IoStatusBlock; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return FALSE; + } + if (lpFileSize) + *lpFileSize = FileStandard.EndOfFile; + + return TRUE; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetCompressedFileSizeA(LPCSTR lpFileName, + LPDWORD lpFileSizeHigh) +{ + PWCHAR FileNameW; + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return INVALID_FILE_SIZE; + + return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh); +} + + +/* + * @implemented + */ +DWORD WINAPI +GetCompressedFileSizeW(LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh) +{ + FILE_COMPRESSION_INFORMATION FileCompression; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE hFile; + + hFile = CreateFileW(lpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return INVALID_FILE_SIZE; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileCompression, + sizeof(FILE_COMPRESSION_INFORMATION), + FileCompressionInformation); + + CloseHandle(hFile); + + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return INVALID_FILE_SIZE; + } + + if(lpFileSizeHigh) + *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart; + + SetLastError(NO_ERROR); + return FileCompression.CompressedFileSize.u.LowPart; +} + + +/* + * @implemented + */ +BOOL WINAPI +GetFileInformationByHandle(HANDLE hFile, + LPBY_HANDLE_FILE_INFORMATION lpFileInformation) +{ + struct + { + FILE_FS_VOLUME_INFORMATION FileFsVolume; + WCHAR Name[255]; + } + FileFsVolume; + + FILE_BASIC_INFORMATION FileBasic; + FILE_INTERNAL_INFORMATION FileInternal; + FILE_STANDARD_INFORMATION FileStandard; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + + if(IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes; + + lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart; + lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart; + + lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart; + lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart; + + lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart; + lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileInternal, + sizeof(FILE_INTERNAL_INFORMATION), + FileInternalInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart; + lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart; + + errCode = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + &FileFsVolume, + sizeof(FileFsVolume), + FileFsVolumeInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks; + lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart; + lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart; + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +GetFileAttributesExW(LPCWSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation) +{ + FILE_NETWORK_OPEN_INFORMATION FileInformation; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING FileName; + NTSTATUS Status; + WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData; + + TRACE("GetFileAttributesExW(%S) called\n", lpFileName); + + + if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Validate and translate the filename */ + if (!RtlDosPathNameToNtPathName_U (lpFileName, + &FileName, + NULL, + NULL)) + { + WARN ("Invalid path '%S'\n", lpFileName); + SetLastError (ERROR_BAD_PATHNAME); + return FALSE; + } + + /* build the object attributes */ + InitializeObjectAttributes (&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Get file attributes */ + Status = NtQueryFullAttributesFile(&ObjectAttributes, + &FileInformation); + + RtlFreeUnicodeString (&FileName); + if (!NT_SUCCESS (Status)) + { + WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation; + FileAttributeData->dwFileAttributes = FileInformation.FileAttributes; + FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart; + FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart; + FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart; + FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart; + FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart; + FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart; + FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart; + FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart; + + return TRUE; +} + +/* + * @implemented + */ +BOOL WINAPI +GetFileAttributesExA(LPCSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation) +{ + PWCHAR FileNameW; + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return FALSE; + + return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation); +} + + +/* + * @implemented + */ +DWORD WINAPI +GetFileAttributesA(LPCSTR lpFileName) +{ + WIN32_FILE_ATTRIBUTE_DATA FileAttributeData; + PWSTR FileNameW; + BOOL ret; + + if (!lpFileName || !(FileNameW = FilenameA2W(lpFileName, FALSE))) + return INVALID_FILE_ATTRIBUTES; + + ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData); + + return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetFileAttributesW(LPCWSTR lpFileName) +{ + WIN32_FILE_ATTRIBUTE_DATA FileAttributeData; + BOOL Result; + + TRACE ("GetFileAttributeW(%S) called\n", lpFileName); + + Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData); + + return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES; +} + + +/* + * @implemented + */ +BOOL WINAPI +GetFileAttributesByHandle(IN HANDLE hFile, + OUT LPDWORD dwFileAttributes, + IN DWORD dwFlags) +{ + FILE_BASIC_INFORMATION FileBasic; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(dwFlags); + + if (IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + Status = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FileBasic), + FileBasicInformation); + if (NT_SUCCESS(Status)) + { + *dwFileAttributes = FileBasic.FileAttributes; + return TRUE; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL WINAPI +SetFileAttributesByHandle(IN HANDLE hFile, + IN DWORD dwFileAttributes, + IN DWORD dwFlags) +{ + FILE_BASIC_INFORMATION FileBasic; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(dwFlags); + + if (IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + Status = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FileBasic), + FileBasicInformation); + if (NT_SUCCESS(Status)) + { + FileBasic.FileAttributes = dwFileAttributes; + + Status = NtSetInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FileBasic), + FileBasicInformation); + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +SetFileAttributesA( + LPCSTR lpFileName, + DWORD dwFileAttributes) +{ + PWCHAR FileNameW; + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return FALSE; + + return SetFileAttributesW(FileNameW, dwFileAttributes); +} + + +/* + * @implemented + */ +BOOL WINAPI +SetFileAttributesW(LPCWSTR lpFileName, + DWORD dwFileAttributes) +{ + FILE_BASIC_INFORMATION FileInformation; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING FileName; + HANDLE FileHandle; + NTSTATUS Status; + + TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes); + + /* Validate and translate the filename */ + if (!RtlDosPathNameToNtPathName_U (lpFileName, + &FileName, + NULL, + NULL)) + { + WARN ("Invalid path\n"); + SetLastError (ERROR_BAD_PATHNAME); + return FALSE; + } + TRACE ("FileName: \'%wZ\'\n", &FileName); + + /* build the object attributes */ + InitializeObjectAttributes (&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the file */ + Status = NtOpenFile (&FileHandle, + SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT); + RtlFreeUnicodeString (&FileName); + if (!NT_SUCCESS (Status)) + { + WARN ("NtOpenFile() failed (Status %lx)\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileInformation, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status); + NtClose (FileHandle); + BaseSetLastNTError (Status); + return FALSE; + } + + FileInformation.FileAttributes = dwFileAttributes; + Status = NtSetInformationFile(FileHandle, + &IoStatusBlock, + &FileInformation, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + NtClose (FileHandle); + if (!NT_SUCCESS(Status)) + { + WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + + + + +/*********************************************************************** + * GetTempFileNameA (KERNEL32.@) + */ +UINT WINAPI +GetTempFileNameA(IN LPCSTR lpPathName, + IN LPCSTR lpPrefixString, + IN UINT uUnique, + OUT LPSTR lpTempFileName) +{ + UINT ID; + NTSTATUS Status; + LPWSTR lpTempFileNameW; + PUNICODE_STRING lpPathNameW; + ANSI_STRING TempFileNameStringA; + UNICODE_STRING lpPrefixStringW, TempFileNameStringW; + + /* Convert strings */ + lpPathNameW = Basep8BitStringToStaticUnicodeString(lpPathName); + if (!lpPathNameW) + { + return 0; + } + + if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW, lpPrefixString)) + { + return 0; + } + + lpTempFileNameW = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + if (!lpTempFileNameW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + RtlFreeUnicodeString(&lpPrefixStringW); + return 0; + } + + /* Call Unicode */ + ID = GetTempFileNameW(lpPathNameW->Buffer, lpPrefixStringW.Buffer, uUnique, lpTempFileNameW); + if (ID) + { + RtlInitUnicodeString(&TempFileNameStringW, lpTempFileNameW); + TempFileNameStringA.Buffer = lpTempFileName; + TempFileNameStringA.MaximumLength = MAX_PATH; + + Status = BasepUnicodeStringTo8BitString(&TempFileNameStringA, &TempFileNameStringW, FALSE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + ID = 0; + } + } + + /* Cleanup */ + RtlFreeUnicodeString(&lpPrefixStringW); + RtlFreeHeap(RtlGetProcessHeap(), 0, lpTempFileNameW); + return ID; + } + + /*********************************************************************** + * GetTempFileNameW (KERNEL32.@) + */ +UINT WINAPI +GetTempFileNameW(IN LPCWSTR lpPathName, + IN LPCWSTR lpPrefixString, + IN UINT uUnique, + OUT LPWSTR lpTempFileName) +{ + CHAR * Let; + HANDLE TempFile; + UINT ID, Num = 0; + CHAR IDString[5]; + WCHAR * TempFileName; + CSR_API_MESSAGE ApiMessage; + DWORD FileAttributes, LastError; + UNICODE_STRING PathNameString, PrefixString; + static const WCHAR Ext[] = { L'.', 't', 'm', 'p', UNICODE_NULL }; + + RtlInitUnicodeString(&PathNameString, lpPathName); + if (PathNameString.Length == 0 || PathNameString.Buffer[(PathNameString.Length / sizeof(WCHAR)) - 1] != L'\\') + { + PathNameString.Length += sizeof(WCHAR); + } + + /* lpTempFileName must be able to contain: PathName, Prefix (3), number(4), .tmp(4) & \0(1) + * See: http://msdn.microsoft.com/en-us/library/aa364991%28v=vs.85%29.aspx + */ + if (PathNameString.Length > (MAX_PATH - 3 - 4 - 4 - 1) * sizeof(WCHAR)) + { + SetLastError(ERROR_BUFFER_OVERFLOW); + return 0; + } + + /* If PathName and TempFileName aren't the same buffer, move PathName to TempFileName */ + if (lpPathName != lpTempFileName) + { + memmove(lpTempFileName, PathNameString.Buffer, PathNameString.Length); + } + + /* PathName MUST BE a path. Check it */ + lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = UNICODE_NULL; + FileAttributes = GetFileAttributesW(lpTempFileName); + if (FileAttributes == INVALID_FILE_ATTRIBUTES) + { + /* Append a '\' if necessary */ + lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = L'\\'; + lpTempFileName[PathNameString.Length / sizeof(WCHAR)] = UNICODE_NULL; + FileAttributes = GetFileAttributesW(lpTempFileName); + if (FileAttributes == INVALID_FILE_ATTRIBUTES) + { + SetLastError(ERROR_DIRECTORY); + return 0; + } + } + if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + SetLastError(ERROR_DIRECTORY); + return 0; + } + + /* Make sure not to mix path & prefix */ + lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = L'\\'; + RtlInitUnicodeString(&PrefixString, lpPrefixString); + if (PrefixString.Length > 3 * sizeof(WCHAR)) + { + PrefixString.Length = 3 * sizeof(WCHAR); + } + + /* Append prefix to path */ + TempFileName = lpTempFileName + PathNameString.Length / sizeof(WCHAR); + memmove(TempFileName, PrefixString.Buffer, PrefixString.Length); + TempFileName += PrefixString.Length / sizeof(WCHAR); + + /* Then, generate filename */ + do + { + /* If user didn't gave any ID, ask Csrss to give one */ + if (!uUnique) + { + CsrClientCallServer(&ApiMessage, NULL, MAKE_CSR_API(GET_TEMP_FILE, CSR_NATIVE), sizeof(CSR_API_MESSAGE)); + if (ApiMessage.Data.GetTempFile.UniqueID == 0) + { + Num++; + continue; + } + + ID = ApiMessage.Data.GetTempFile.UniqueID; + } + else + { + ID = uUnique; + } + + /* Convert that ID to wchar */ + RtlIntegerToChar(ID, 0x10, sizeof(IDString), IDString); + Let = IDString; + do + { + *(TempFileName++) = RtlAnsiCharToUnicodeChar(&Let); + } while (*Let != 0); + + /* Append extension & UNICODE_NULL */ + memmove(TempFileName, Ext, sizeof(Ext) + sizeof(WCHAR)); + + /* If user provided its ID, just return */ + if (uUnique) + { + return uUnique; + } + + /* Then, try to create file */ + if (!RtlIsDosDeviceName_U(lpTempFileName)) + { + TempFile = CreateFileW(lpTempFileName, + GENERIC_READ, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + 0); + if (TempFile != INVALID_HANDLE_VALUE) + { + NtClose(TempFile); + DPRINT("Temp file: %S\n", lpTempFileName); + return ID; + } + + LastError = GetLastError(); + /* There is no need to recover from those errors, they would hit next step */ + if (LastError == ERROR_INVALID_PARAMETER || LastError == ERROR_CANNOT_MAKE || + LastError == ERROR_WRITE_PROTECT || LastError == ERROR_NETWORK_ACCESS_DENIED || + LastError == ERROR_DISK_FULL || LastError == ERROR_INVALID_NAME || + LastError == ERROR_BAD_PATHNAME || LastError == ERROR_NO_INHERITANCE || + LastError == ERROR_DISK_CORRUPT || + (LastError == ERROR_ACCESS_DENIED && NtCurrentTeb()->LastStatusValue != STATUS_FILE_IS_A_DIRECTORY)) + { + break; + } + } + Num++; + } while (Num & 0xFFFF); + + return 0; +} + + + + + +/* + * @implemented + */ +BOOL WINAPI +GetFileTime(IN HANDLE hFile, + OUT LPFILETIME lpCreationTime OPTIONAL, + OUT LPFILETIME lpLastAccessTime OPTIONAL, + OUT LPFILETIME lpLastWriteTime OPTIONAL) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; + + if(IsConsoleHandle(hFile)) + { + BaseSetLastNTError(STATUS_INVALID_HANDLE); + return FALSE; + } + + Status = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if (lpCreationTime) + { + lpCreationTime->dwLowDateTime = FileBasic.CreationTime.LowPart; + lpCreationTime->dwHighDateTime = FileBasic.CreationTime.HighPart; + } + + if (lpLastAccessTime) + { + lpLastAccessTime->dwLowDateTime = FileBasic.LastAccessTime.LowPart; + lpLastAccessTime->dwHighDateTime = FileBasic.LastAccessTime.HighPart; + } + + if (lpLastWriteTime) + { + lpLastWriteTime->dwLowDateTime = FileBasic.LastWriteTime.LowPart; + lpLastWriteTime->dwHighDateTime = FileBasic.LastWriteTime.HighPart; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +SetFileTime(IN HANDLE hFile, + CONST FILETIME *lpCreationTime OPTIONAL, + CONST FILETIME *lpLastAccessTime OPTIONAL, + CONST FILETIME *lpLastWriteTime OPTIONAL) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; + + if(IsConsoleHandle(hFile)) + { + BaseSetLastNTError(STATUS_INVALID_HANDLE); + return FALSE; + } + + memset(&FileBasic, 0, sizeof(FILE_BASIC_INFORMATION)); + + if (lpCreationTime) + { + FileBasic.CreationTime.LowPart = lpCreationTime->dwLowDateTime; + FileBasic.CreationTime.HighPart = lpCreationTime->dwHighDateTime; + } + + if (lpLastAccessTime) + { + FileBasic.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime; + FileBasic.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime; + } + + if (lpLastWriteTime) + { + FileBasic.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime; + FileBasic.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime; + } + + Status = NtSetInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set. + * + * @implemented + */ +BOOL WINAPI +SetEndOfFile(HANDLE hFile) +{ + IO_STATUS_BLOCK IoStatusBlock; + FILE_END_OF_FILE_INFORMATION EndOfFileInfo; + FILE_ALLOCATION_INFORMATION FileAllocationInfo; + FILE_POSITION_INFORMATION FilePosInfo; + NTSTATUS Status; + + if(IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + //get current position + Status = NtQueryInformationFile( + hFile, + &IoStatusBlock, + &FilePosInfo, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation + ); + + if (!NT_SUCCESS(Status)){ + BaseSetLastNTError(Status); + return FALSE; + } + + EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart; + + /* + NOTE: + This call is not supposed to free up any space after the eof marker + if the file gets truncated. We have to deallocate the space explicitly afterwards. + But...most file systems dispatch both FileEndOfFileInformation + and FileAllocationInformation as they were the same command. + + */ + Status = NtSetInformationFile( + hFile, + &IoStatusBlock, //out + &EndOfFileInfo, + sizeof(FILE_END_OF_FILE_INFORMATION), + FileEndOfFileInformation + ); + + if (!NT_SUCCESS(Status)){ + BaseSetLastNTError(Status); + return FALSE; + } + + FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart; + + + Status = NtSetInformationFile( + hFile, + &IoStatusBlock, //out + &FileAllocationInfo, + sizeof(FILE_ALLOCATION_INFORMATION), + FileAllocationInformation + ); + + if (!NT_SUCCESS(Status)){ + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; + +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetFileValidData( + HANDLE hFile, + LONGLONG ValidDataLength + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation; + NTSTATUS Status; + + ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength; + + Status = NtSetInformationFile( + hFile, + &IoStatusBlock, //out + &ValidDataLengthInformation, + sizeof(FILE_VALID_DATA_LENGTH_INFORMATION), + FileValidDataLengthInformation + ); + + if (!NT_SUCCESS(Status)){ + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + + +/* + * @implemented + */ +BOOL +WINAPI +SetFileShortNameW( + HANDLE hFile, + LPCWSTR lpShortName) +{ + NTSTATUS Status; + ULONG NeededSize; + UNICODE_STRING ShortName; + IO_STATUS_BLOCK IoStatusBlock; + PFILE_NAME_INFORMATION FileNameInfo; + + if(IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if(!lpShortName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlInitUnicodeString(&ShortName, lpShortName); + + NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR); + if(!(FileNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize))) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + FileNameInfo->FileNameLength = ShortName.Length; + RtlCopyMemory(FileNameInfo->FileName, ShortName.Buffer, ShortName.Length); + + Status = NtSetInformationFile(hFile, + &IoStatusBlock, //out + FileNameInfo, + NeededSize, + FileShortNameInformation); + + RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo); + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetFileShortNameA( + HANDLE hFile, + LPCSTR lpShortName + ) +{ + PWCHAR ShortNameW; + + if(IsConsoleHandle(hFile)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if(!lpShortName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!(ShortNameW = FilenameA2W(lpShortName, FALSE))) + return FALSE; + + return SetFileShortNameW(hFile, ShortNameW); +} + + +/* + * @implemented + */ +BOOL +WINAPI +CheckNameLegalDOS8Dot3W( + LPCWSTR lpName, + LPSTR lpOemName OPTIONAL, + DWORD OemNameSize OPTIONAL, + PBOOL pbNameContainsSpaces OPTIONAL, + PBOOL pbNameLegal + ) +{ + UNICODE_STRING Name; + ANSI_STRING AnsiName; + + if(lpName == NULL || + (lpOemName == NULL && OemNameSize != 0) || + pbNameLegal == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(lpOemName != NULL) + { + AnsiName.Buffer = lpOemName; + AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR); + AnsiName.Length = 0; + } + + RtlInitUnicodeString(&Name, lpName); + + *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name, + (lpOemName ? &AnsiName : NULL), + (BOOLEAN*)pbNameContainsSpaces); + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CheckNameLegalDOS8Dot3A( + LPCSTR lpName, + LPSTR lpOemName OPTIONAL, + DWORD OemNameSize OPTIONAL, + PBOOL pbNameContainsSpaces OPTIONAL, + PBOOL pbNameLegal + ) +{ + UNICODE_STRING Name; + ANSI_STRING AnsiName, AnsiInputName; + NTSTATUS Status; + + if(lpName == NULL || + (lpOemName == NULL && OemNameSize != 0) || + pbNameLegal == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(lpOemName != NULL) + { + AnsiName.Buffer = lpOemName; + AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR); + AnsiName.Length = 0; + } + + RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName); + if(bIsFileApiAnsi) + Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE); + else + Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE); + + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name, + (lpOemName ? &AnsiName : NULL), + (BOOLEAN*)pbNameContainsSpaces); + + RtlFreeUnicodeString(&Name); + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +ReplaceFileA( + LPCSTR lpReplacedFileName, + LPCSTR lpReplacementFileName, + LPCSTR lpBackupFileName, + DWORD dwReplaceFlags, + LPVOID lpExclude, + LPVOID lpReserved + ) +{ + WCHAR *replacedW, *replacementW, *backupW = NULL; + BOOL ret; + + /* This function only makes sense when the first two parameters are defined */ + if (!lpReplacedFileName || !(replacedW = FilenameA2W(lpReplacedFileName, TRUE))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!lpReplacementFileName || !(replacementW = FilenameA2W(lpReplacementFileName, TRUE))) + { + HeapFree(GetProcessHeap(), 0, replacedW); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* The backup parameter, however, is optional */ + if (lpBackupFileName) + { + if (!(backupW = FilenameA2W(lpBackupFileName, TRUE))) + { + HeapFree(GetProcessHeap(), 0, replacedW); + HeapFree(GetProcessHeap(), 0, replacementW); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + } + + ret = ReplaceFileW(replacedW, replacementW, backupW, dwReplaceFlags, lpExclude, lpReserved); + HeapFree(GetProcessHeap(), 0, replacedW); + HeapFree(GetProcessHeap(), 0, replacementW); + HeapFree(GetProcessHeap(), 0, backupW); + + return ret; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +ReplaceFileW( + LPCWSTR lpReplacedFileName, + LPCWSTR lpReplacementFileName, + LPCWSTR lpBackupFileName, + DWORD dwReplaceFlags, + LPVOID lpExclude, + LPVOID lpReserved + ) +{ + HANDLE hReplaced = NULL, hReplacement = NULL; + UNICODE_STRING NtReplacedName = { 0, 0, NULL }; + UNICODE_STRING NtReplacementName = { 0, 0, NULL }; + DWORD Error = ERROR_SUCCESS; + NTSTATUS Status; + BOOL Ret = FALSE; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + PVOID Buffer = NULL ; + + if (dwReplaceFlags) + FIXME("Ignoring flags %x\n", dwReplaceFlags); + + /* First two arguments are mandatory */ + if (!lpReplacedFileName || !lpReplacementFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Back it up */ + if(lpBackupFileName) + { + if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE)) + { + Error = GetLastError(); + goto Cleanup ; + } + } + + /* Open the "replaced" file for reading and writing */ + if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL))) + { + Error = ERROR_PATH_NOT_FOUND; + goto Cleanup; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtReplacedName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&hReplaced, + GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + Error = ERROR_FILE_NOT_FOUND; + else + Error = ERROR_UNABLE_TO_REMOVE_REPLACED; + goto Cleanup; + } + + /* Blank it */ + SetEndOfFile(hReplaced) ; + + /* + * Open the replacement file for reading, writing, and deleting + * (deleting is needed when finished) + */ + if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL))) + { + Error = ERROR_PATH_NOT_FOUND; + goto Cleanup; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtReplacementName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&hReplacement, + GENERIC_READ | DELETE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); + + if (!NT_SUCCESS(Status)) + { + Error = RtlNtStatusToDosError(Status); + goto Cleanup; + } + + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ; + if (!Buffer) + { + Error = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup ; + } + while (Status != STATUS_END_OF_FILE) + { + Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ; + if (NT_SUCCESS(Status)) + { + Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer, + IoStatusBlock.Information, NULL, NULL) ; + if (!NT_SUCCESS(Status)) + { + Error = RtlNtStatusToDosError(Status); + goto Cleanup; + } + } + else if (Status != STATUS_END_OF_FILE) + { + Error = RtlNtStatusToDosError(Status); + goto Cleanup; + } + } + + Ret = TRUE; + + /* Perform resource cleanup */ +Cleanup: + if (hReplaced) NtClose(hReplaced); + if (hReplacement) NtClose(hReplacement); + if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + if (NtReplacementName.Buffer) + RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer); + if (NtReplacedName.Buffer) + RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer); + + /* If there was an error, set the error code */ + if(!Ret) + { + TRACE("ReplaceFileW failed (error=%d)\n", Error); + SetLastError(Error); + } + return Ret; +} + +/* + * @implemented + */ +BOOL +WINAPI +ReadFileScatter(HANDLE hFile, + FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToRead, + LPDWORD lpReserved, + LPOVERLAPPED lpOverlapped) +{ + PIO_STATUS_BLOCK pIOStatus; + LARGE_INTEGER Offset; + NTSTATUS Status; + + DPRINT("(%p %p %u %p)\n", hFile, aSegmentArray, nNumberOfBytesToRead, lpOverlapped); + + Offset.LowPart = lpOverlapped->Offset; + Offset.HighPart = lpOverlapped->OffsetHigh; + pIOStatus = (PIO_STATUS_BLOCK) lpOverlapped; + pIOStatus->Status = STATUS_PENDING; + pIOStatus->Information = 0; + + Status = NtReadFileScatter(hFile, + NULL, + NULL, + NULL, + pIOStatus, + aSegmentArray, + nNumberOfBytesToRead, + &Offset, + NULL); + + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +WriteFileGather(HANDLE hFile, + FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToWrite, + LPDWORD lpReserved, + LPOVERLAPPED lpOverlapped) +{ + PIO_STATUS_BLOCK IOStatus; + LARGE_INTEGER Offset; + NTSTATUS Status; + + DPRINT("%p %p %u %p\n", hFile, aSegmentArray, nNumberOfBytesToWrite, lpOverlapped); + + Offset.LowPart = lpOverlapped->Offset; + Offset.HighPart = lpOverlapped->OffsetHigh; + IOStatus = (PIO_STATUS_BLOCK) lpOverlapped; + IOStatus->Status = STATUS_PENDING; + IOStatus->Information = 0; + + Status = NtWriteFileGather(hFile, + NULL, + NULL, + NULL, + IOStatus, + aSegmentArray, + nNumberOfBytesToWrite, + &Offset, + NULL); + + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; +} + +BOOL +WINAPI +OpenDataFile(HANDLE hFile, DWORD dwUnused) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +PrivMoveFileIdentityW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +HANDLE +WINAPI +ReOpenFile(IN HANDLE hOriginalFile, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN DWORD dwFlags) +{ + STUB; + return INVALID_HANDLE_VALUE; +} + +BOOLEAN +WINAPI +Wow64EnableWow64FsRedirection (BOOLEAN Wow64EnableWow64FsRedirection) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +Wow64DisableWow64FsRedirection (VOID ** pv) +{ + STUB; + return FALSE; +} + +BOOL +WINAPI +Wow64RevertWow64FsRedirection (VOID * pv) +{ + STUB; + return FALSE; +} + + +/* EOF */ diff --git a/dll/win32/kernel32/mem/section.c b/dll/win32/kernel32/client/file/filemap.c similarity index 88% rename from dll/win32/kernel32/mem/section.c rename to dll/win32/kernel32/client/file/filemap.c index 705a8c360de..46882e0ca72 100644 --- a/dll/win32/kernel32/mem/section.c +++ b/dll/win32/kernel32/client/file/filemap.c @@ -27,38 +27,14 @@ CreateFileMappingA(IN HANDLE hFile, IN DWORD dwMaximumSizeLow, IN LPCSTR lpName) { - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - LPCWSTR UnicodeName = NULL; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Otherwise, save the buffer */ - UnicodeName = (LPCWSTR)UnicodeCache->Buffer; - } - - /* Call the Unicode version */ - return CreateFileMappingW(hFile, - lpFileMappingAttributes, - flProtect, - dwMaximumSizeHigh, - dwMaximumSizeLow, - UnicodeName); + /* Call the W(ide) function */ + ConvertWin32AnsiObjectApiToUnicodeApi(FileMapping, + lpName, + hFile, + lpFileMappingAttributes, + flProtect, + dwMaximumSizeHigh, + dwMaximumSizeLow); } /* @@ -148,7 +124,7 @@ CreateFileMappingW(HANDLE hFile, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -215,7 +191,7 @@ MapViewOfFileEx(HANDLE hFileMappingObject, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -257,7 +233,7 @@ UnmapViewOfFile(LPCVOID lpBaseAddress) if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -290,7 +266,7 @@ OpenFileMappingA(DWORD dwDesiredAccess, if (!NT_SUCCESS(Status)) { /* Conversion failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } } @@ -347,7 +323,7 @@ OpenFileMappingW(DWORD dwDesiredAccess, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -379,7 +355,7 @@ FlushViewOfFile(LPCVOID lpBaseAddress, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } diff --git a/dll/win32/kernel32/client/file/find.c b/dll/win32/kernel32/client/file/find.c new file mode 100644 index 00000000000..91fc17a422d --- /dev/null +++ b/dll/win32/kernel32/client/file/find.c @@ -0,0 +1,985 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Pierre Schweitzer (pierre.schweitzer@reactos.org) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* TYPES ********************************************************************/ + +#define FIND_DATA_SIZE 0x4000 + +#define FIND_DEVICE_HANDLE ((HANDLE)0x1) + +typedef struct _KERNEL32_FIND_FILE_DATA +{ + HANDLE DirectoryHandle; + RTL_CRITICAL_SECTION Lock; + PFILE_BOTH_DIR_INFORMATION pFileInfo; + BOOLEAN DirectoryOnly; + BOOLEAN HasMoreData; + BOOLEAN HasData; + BOOLEAN LockInitialized; +} KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA; + +typedef struct _KERNEL32_FIND_STREAM_DATA +{ + STREAM_INFO_LEVELS InfoLevel; + PFILE_STREAM_INFORMATION pFileStreamInfo; + PFILE_STREAM_INFORMATION pCurrent; +} KERNEL32_FIND_STREAM_DATA, *PKERNEL32_FIND_STREAM_DATA; + +typedef enum _KERNEL32_FIND_DATA_TYPE +{ + FileFind, + StreamFind +} KERNEL32_FIND_DATA_TYPE; + +typedef struct _KERNEL32_FIND_DATA_HEADER +{ + KERNEL32_FIND_DATA_TYPE Type; +} KERNEL32_FIND_DATA_HEADER, *PKERNEL32_FIND_DATA_HEADER; + + +/* FUNCTIONS ****************************************************************/ + +static VOID +InternalCopyDeviceFindDataW(LPWIN32_FIND_DATAW lpFindFileData, + LPCWSTR lpFileName, + ULONG DeviceNameInfo) +{ + UNICODE_STRING DeviceName; + + DeviceName.Length = DeviceName.MaximumLength = (USHORT)(DeviceNameInfo & 0xFFFF); + DeviceName.Buffer = (LPWSTR)((ULONG_PTR)lpFileName + (DeviceNameInfo >> 16)); + + /* Return the data */ + RtlZeroMemory(lpFindFileData, + sizeof(*lpFindFileData)); + lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE; + RtlCopyMemory(lpFindFileData->cFileName, + DeviceName.Buffer, + DeviceName.Length); +} + +static VOID +InternalCopyFindDataW(LPWIN32_FIND_DATAW lpFindFileData, + PFILE_BOTH_DIR_INFORMATION lpFileInfo) +{ + lpFindFileData->dwFileAttributes = lpFileInfo->FileAttributes; + + lpFindFileData->ftCreationTime.dwHighDateTime = lpFileInfo->CreationTime.u.HighPart; + lpFindFileData->ftCreationTime.dwLowDateTime = lpFileInfo->CreationTime.u.LowPart; + + lpFindFileData->ftLastAccessTime.dwHighDateTime = lpFileInfo->LastAccessTime.u.HighPart; + lpFindFileData->ftLastAccessTime.dwLowDateTime = lpFileInfo->LastAccessTime.u.LowPart; + + lpFindFileData->ftLastWriteTime.dwHighDateTime = lpFileInfo->LastWriteTime.u.HighPart; + lpFindFileData->ftLastWriteTime.dwLowDateTime = lpFileInfo->LastWriteTime.u.LowPart; + + lpFindFileData->nFileSizeHigh = lpFileInfo->EndOfFile.u.HighPart; + lpFindFileData->nFileSizeLow = lpFileInfo->EndOfFile.u.LowPart; + + memcpy (lpFindFileData->cFileName, lpFileInfo->FileName, lpFileInfo->FileNameLength); + lpFindFileData->cFileName[lpFileInfo->FileNameLength / sizeof(WCHAR)] = 0; + + memcpy (lpFindFileData->cAlternateFileName, lpFileInfo->ShortName, lpFileInfo->ShortNameLength); + lpFindFileData->cAlternateFileName[lpFileInfo->ShortNameLength / sizeof(WCHAR)] = 0; +} + + +/* + * @implemented + */ +BOOL +WINAPI +InternalFindNextFile ( + HANDLE hFindFile, + PUNICODE_STRING SearchPattern, + PVOID lpFindFileData + ) +{ + PKERNEL32_FIND_DATA_HEADER IHeader; + PKERNEL32_FIND_FILE_DATA IData; + IO_STATUS_BLOCK IoStatusBlock; + BOOLEAN Locked = FALSE; + PFILE_BOTH_DIR_INFORMATION Buffer, FoundFile = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + TRACE("InternalFindNextFile(%lx, %wZ)\n", hFindFile, SearchPattern); + + if (hFindFile != FIND_DEVICE_HANDLE) + { + IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile; + if (hFindFile == NULL || hFindFile == INVALID_HANDLE_VALUE || + IHeader->Type != FileFind) + { + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1); + Buffer = (PFILE_BOTH_DIR_INFORMATION)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA)); + + if (SearchPattern == NULL) + { + RtlEnterCriticalSection(&IData->Lock); + Locked = TRUE; + } + + do + { + if (IData->HasData) + { + if (!IData->DirectoryOnly || (IData->pFileInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + FoundFile = IData->pFileInfo; + } + + if (IData->pFileInfo->NextEntryOffset != 0) + { + ULONG_PTR BufferEnd; + + IData->pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((ULONG_PTR)IData->pFileInfo + IData->pFileInfo->NextEntryOffset); + + /* Be paranoid and make sure that the next entry is completely there */ + BufferEnd = (ULONG_PTR)Buffer + FIND_DATA_SIZE; + if (BufferEnd < (ULONG_PTR)IData->pFileInfo || + BufferEnd < (ULONG_PTR)&IData->pFileInfo->FileNameLength + sizeof(IData->pFileInfo->FileNameLength) || + BufferEnd <= (ULONG_PTR)&IData->pFileInfo->FileName[IData->pFileInfo->FileNameLength]) + { + goto NeedMoreData; + } + } + else + { +NeedMoreData: + IData->HasData = FALSE; + + if (!IData->HasMoreData) + break; + } + } + else + { + IData->pFileInfo = Buffer; + IData->pFileInfo->NextEntryOffset = 0; + Status = NtQueryDirectoryFile (IData->DirectoryHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + (PVOID)IData->pFileInfo, + FIND_DATA_SIZE, + FileBothDirectoryInformation, + FALSE, + SearchPattern, + SearchPattern != NULL); + + if (Status == STATUS_BUFFER_OVERFLOW) + { + IData->HasMoreData = TRUE; + Status = STATUS_SUCCESS; + } + else + { + if (!NT_SUCCESS(Status)) + break; + + IData->HasMoreData = FALSE; + } + + IData->HasData = TRUE; + SearchPattern = NULL; + } + + } while (FoundFile == NULL); + + if (FoundFile != NULL) + { + _SEH2_TRY + { + InternalCopyFindDataW(lpFindFileData, + FoundFile); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; + } + + if (Locked) + RtlLeaveCriticalSection(&IData->Lock); + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + else if (FoundFile == NULL) + { + SetLastError (ERROR_NO_MORE_FILES); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +InternalFindFirstFile ( + LPCWSTR lpFileName, + BOOLEAN DirectoryOnly, + PVOID lpFindFileData + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PKERNEL32_FIND_DATA_HEADER IHeader; + PKERNEL32_FIND_FILE_DATA IData; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU, FileName, PathFileName; + NTSTATUS Status; + PWSTR NtPathBuffer; + BOOLEAN RemovedLastChar = FALSE; + BOOL bResult; + RTL_RELATIVE_NAME_U DirInfo; + ULONG DeviceNameInfo; + HANDLE hDirectory = NULL; + + TRACE("FindFirstFileW(lpFileName %S)\n", + lpFileName); + + RtlZeroMemory(&PathFileName, + sizeof(PathFileName)); + RtlInitUnicodeString(&FileName, + lpFileName); + + bResult = RtlDosPathNameToNtPathName_U (lpFileName, + &NtPathU, + (PCWSTR *)((ULONG_PTR)&PathFileName.Buffer), + &DirInfo); + if (FALSE == bResult) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return INVALID_HANDLE_VALUE; + } + + /* Save the buffer pointer for later, we need to free it! */ + NtPathBuffer = NtPathU.Buffer; + + /* If there is a file name/pattern then determine it's length */ + if (PathFileName.Buffer != NULL) + { + PathFileName.Length = NtPathU.Length - + (USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)NtPathU.Buffer); + } + PathFileName.MaximumLength = PathFileName.Length; + + if (DirInfo.RelativeName.Length != 0 && DirInfo.RelativeName.Buffer != PathFileName.Buffer) + { + if (PathFileName.Buffer != NULL) + { + /* This is a relative path to DirInfo.ContainingDirectory, adjust NtPathU! */ + NtPathU.Length = NtPathU.MaximumLength = + (USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)DirInfo.RelativeName.Buffer); + NtPathU.Buffer = DirInfo.RelativeName.Buffer; + } + } + else + { + /* This is an absolute path, NtPathU receives the full path */ + DirInfo.ContainingDirectory = NULL; + if (PathFileName.Buffer != NULL) + { + NtPathU.Length = NtPathU.MaximumLength = + (USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)NtPathU.Buffer); + } + } + + /* Remove the last character of the path (Unless the path is a drive and + ends with ":\"). If the caller however supplies a path to a device, such + as "C:\NUL" then the last character gets cut off, which later results in + NtOpenFile to return STATUS_OBJECT_NAME_NOT_FOUND, which in turn triggers + a fake DOS device check with RtlIsDosDeviceName_U. However, if there is a + real device with a name eg. "NU" in the system, FindFirstFile will succeed, + rendering the fake DOS device check useless... Why would they invent such a + stupid and broken behavior?! */ + if (NtPathU.Length >= 2 * sizeof(WCHAR) && + NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 1] != L'\\' && + NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 2] != L':') + { + NtPathU.Length -= sizeof(WCHAR); + RemovedLastChar = TRUE; + } + + TRACE("lpFileName: \"%ws\"\n", lpFileName); + TRACE("NtPathU: \"%wZ\"\n", &NtPathU); + TRACE("PathFileName: \"%wZ\"\n", &PathFileName); + TRACE("RelativeTo: 0x%p\n", DirInfo.ContainingDirectory); + + InitializeObjectAttributes (&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + DirInfo.ContainingDirectory, + NULL); + + Status = NtOpenFile (&hDirectory, + FILE_LIST_DIRECTORY | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + + if (Status == STATUS_NOT_A_DIRECTORY && RemovedLastChar) + { + /* Try again, this time with the last character ... */ + NtPathU.Length += sizeof(WCHAR); + + Status = NtOpenFile (&hDirectory, + FILE_LIST_DIRECTORY | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + + NtPathU.Length += sizeof(WCHAR); + } + + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap (hProcessHeap, + 0, + NtPathBuffer); + + /* See if the application tries to look for a DOS device */ + DeviceNameInfo = RtlIsDosDeviceName_U((PWSTR)((ULONG_PTR)lpFileName)); + if (DeviceNameInfo != 0) + { + InternalCopyDeviceFindDataW(lpFindFileData, + lpFileName, + DeviceNameInfo); + + return FIND_DEVICE_HANDLE; + } + + BaseSetLastNTError (Status); + return INVALID_HANDLE_VALUE; + } + + if (PathFileName.Length == 0) + { + /* No file part?! */ + NtClose(hDirectory); + RtlFreeHeap (hProcessHeap, + 0, + NtPathBuffer); + SetLastError(ERROR_FILE_NOT_FOUND); + return INVALID_HANDLE_VALUE; + } + + IHeader = RtlAllocateHeap (hProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(KERNEL32_FIND_DATA_HEADER) + + sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE); + if (NULL == IHeader) + { + RtlFreeHeap (hProcessHeap, + 0, + NtPathBuffer); + NtClose(hDirectory); + + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return INVALID_HANDLE_VALUE; + } + + IHeader->Type = FileFind; + IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1); + IData->DirectoryHandle = hDirectory; + IData->HasMoreData = TRUE; + + /* change pattern: "*.*" --> "*" */ + if (PathFileName.Length == 6 && + RtlCompareMemory(PathFileName.Buffer, + L"*.*", + 6) == 6) + { + PathFileName.Length = 2; + } + + IData->pFileInfo = (PVOID)((ULONG_PTR)IData + sizeof(KERNEL32_FIND_FILE_DATA)); + IData->pFileInfo->FileIndex = 0; + IData->DirectoryOnly = DirectoryOnly; + + bResult = InternalFindNextFile((HANDLE)IHeader, + &PathFileName, + lpFindFileData); + + RtlFreeHeap (hProcessHeap, + 0, + NtPathBuffer); + + if (!bResult) + { + FindClose((HANDLE)IHeader); + return INVALID_HANDLE_VALUE; + } + + RtlInitializeCriticalSection(&IData->Lock); + IData->LockInitialized = TRUE; + + return (HANDLE)IHeader; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +FindFirstFileA(IN LPCSTR lpFileName, + OUT LPWIN32_FIND_DATAA lpFindFileData) +{ + HANDLE hSearch; + NTSTATUS Status; + ANSI_STRING Ansi; + UNICODE_STRING UTF8; + PUNICODE_STRING lpFileNameW; + WIN32_FIND_DATAW FindFileDataW; + + lpFileNameW = Basep8BitStringToStaticUnicodeString(lpFileName); + if (!lpFileNameW) + { + return INVALID_HANDLE_VALUE; + } + + hSearch = FindFirstFileExW(lpFileNameW->Buffer, + FindExInfoStandard, + &FindFileDataW, + FindExSearchNameMatch, + NULL, 0); + if (hSearch == INVALID_HANDLE_VALUE) + { + return INVALID_HANDLE_VALUE; + } + + memcpy(lpFindFileData, &FindFileDataW, FIELD_OFFSET(WIN32_FIND_DATA, cFileName)); + + RtlInitUnicodeString(&UTF8, FindFileDataW.cFileName); + Ansi.Buffer = lpFindFileData->cFileName; + Ansi.Length = 0; + Ansi.MaximumLength = MAX_PATH; + Status = BasepUnicodeStringTo8BitString(&Ansi, &UTF8, FALSE); + if (!NT_SUCCESS(Status)) + { + FindClose(hSearch); + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + RtlInitUnicodeString(&UTF8, FindFileDataW.cAlternateFileName); + Ansi.Buffer = lpFindFileData->cAlternateFileName; + Ansi.Length = 0; + Ansi.MaximumLength = 14; + Status = BasepUnicodeStringTo8BitString(&Ansi, &UTF8, FALSE); + if (!NT_SUCCESS(Status)) + { + FindClose(hSearch); + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + return hSearch; +} + + +/* + * @implemented + */ +BOOL +WINAPI +FindNextFileA(IN HANDLE hFindFile, + OUT LPWIN32_FIND_DATAA lpFindFileData) +{ + NTSTATUS Status; + ANSI_STRING Ansi; + UNICODE_STRING UTF8; + WIN32_FIND_DATAW FindFileDataW; + + if (!FindNextFileW(hFindFile, &FindFileDataW)) + { + return FALSE; + } + + memcpy(lpFindFileData, &FindFileDataW, FIELD_OFFSET(WIN32_FIND_DATA, cFileName)); + + RtlInitUnicodeString(&UTF8, FindFileDataW.cFileName); + Ansi.Buffer = lpFindFileData->cFileName; + Ansi.Length = 0; + Ansi.MaximumLength = MAX_PATH; + Status = BasepUnicodeStringTo8BitString(&Ansi, &UTF8, FALSE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + RtlInitUnicodeString(&UTF8, FindFileDataW.cAlternateFileName); + Ansi.Buffer = lpFindFileData->cAlternateFileName; + Ansi.Length = 0; + Ansi.MaximumLength = 14; + Status = BasepUnicodeStringTo8BitString(&Ansi, &UTF8, FALSE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +FindClose ( + HANDLE hFindFile + ) +{ + PKERNEL32_FIND_DATA_HEADER IHeader; + + TRACE("FindClose(hFindFile %x)\n",hFindFile); + + if (hFindFile == FIND_DEVICE_HANDLE) + return TRUE; + + if (!hFindFile || hFindFile == INVALID_HANDLE_VALUE) + { + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindFile; + + switch (IHeader->Type) + { + case FileFind: + { + PKERNEL32_FIND_FILE_DATA IData = (PKERNEL32_FIND_FILE_DATA)(IHeader + 1); + CloseHandle (IData->DirectoryHandle); + if (IData->LockInitialized) + RtlDeleteCriticalSection(&IData->Lock); + IData->LockInitialized = FALSE; + break; + } + + case StreamFind: + { + PKERNEL32_FIND_STREAM_DATA IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1); + if (IData->pFileStreamInfo != NULL) + { + RtlFreeHeap (hProcessHeap, 0, IData->pFileStreamInfo); + } + break; + } + + default: + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + RtlFreeHeap (hProcessHeap, 0, IHeader); + + return TRUE; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +FindFirstFileW(IN LPCWSTR lpFileName, + OUT LPWIN32_FIND_DATAW lpFindFileData) +{ + return FindFirstFileExW(lpFileName, + FindExInfoStandard, + lpFindFileData, + FindExSearchNameMatch, + NULL, + 0); +} + +/* + * @implemented + */ +BOOL +WINAPI +FindNextFileW(IN HANDLE hFindFile, + OUT LPWIN32_FIND_DATAW lpFindFileData) +{ + return InternalFindNextFile(hFindFile, + NULL, + lpFindFileData); +} + + +/* + * @unimplemented + */ +HANDLE +WINAPI +FindFirstFileExW(IN LPCWSTR lpFileName, + IN FINDEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFindFileData, + IN FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + IN DWORD dwAdditionalFlags) +{ + if (fInfoLevelId != FindExInfoStandard) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + if (fSearchOp == FindExSearchNameMatch || fSearchOp == FindExSearchLimitToDirectories) + { + if (lpSearchFilter) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + return InternalFindFirstFile (lpFileName, + fSearchOp == FindExSearchLimitToDirectories, + lpFindFileData); + } + + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; +} + +/* + * @unimplemented + */ +HANDLE +WINAPI +FindFirstFileExA(IN LPCSTR lpFileName, + IN FINDEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFindFileData, + IN FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + IN DWORD dwAdditionalFlags) +{ + HANDLE hSearch; + NTSTATUS Status; + ANSI_STRING Ansi; + UNICODE_STRING UTF8; + PUNICODE_STRING lpFileNameW; + WIN32_FIND_DATAW FindFileDataW; + + lpFileNameW = Basep8BitStringToStaticUnicodeString(lpFileName); + if (!lpFileNameW) + { + return INVALID_HANDLE_VALUE; + } + + hSearch = FindFirstFileExW(lpFileNameW->Buffer, + fInfoLevelId, + &FindFileDataW, + fSearchOp, + lpSearchFilter, + dwAdditionalFlags); + if (hSearch == INVALID_HANDLE_VALUE) + { + return INVALID_HANDLE_VALUE; + } + + memcpy(lpFindFileData, &FindFileDataW, FIELD_OFFSET(WIN32_FIND_DATA, cFileName)); + + RtlInitUnicodeString(&UTF8, FindFileDataW.cFileName); + Ansi.Buffer = ((LPWIN32_FIND_DATAA)lpFindFileData)->cFileName; + Ansi.Length = 0; + Ansi.MaximumLength = MAX_PATH; + Status = BasepUnicodeStringTo8BitString(&Ansi, &UTF8, FALSE); + if (!NT_SUCCESS(Status)) + { + FindClose(hSearch); + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + RtlInitUnicodeString(&UTF8, FindFileDataW.cAlternateFileName); + Ansi.Buffer = ((LPWIN32_FIND_DATAA)lpFindFileData)->cAlternateFileName; + Ansi.Length = 0; + Ansi.MaximumLength = 14; + Status = BasepUnicodeStringTo8BitString(&Ansi, &UTF8, FALSE); + if (!NT_SUCCESS(Status)) + { + FindClose(hSearch); + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + return hSearch; +} + + +static VOID +InternalCopyStreamInfo(IN OUT PKERNEL32_FIND_STREAM_DATA IData, + OUT LPVOID lpFindStreamData) +{ + ASSERT(IData->pCurrent); + + switch (IData->InfoLevel) + { + case FindStreamInfoStandard: + { + ULONG StreamNameLen; + WIN32_FIND_STREAM_DATA *StreamData = (WIN32_FIND_STREAM_DATA*)lpFindStreamData; + + StreamNameLen = IData->pCurrent->StreamNameLength; + if (StreamNameLen > sizeof(StreamData->cStreamName) - sizeof(WCHAR)) + StreamNameLen = sizeof(StreamData->cStreamName) - sizeof(WCHAR); + + StreamData->StreamSize.QuadPart = IData->pCurrent->StreamSize.QuadPart; + RtlCopyMemory(StreamData->cStreamName, + IData->pCurrent->StreamName, + StreamNameLen); + StreamData->cStreamName[StreamNameLen / sizeof(WCHAR)] = L'\0'; + break; + } + + default: + ASSERT(FALSE); + break; + } +} + + +/* + * @implemented + */ +HANDLE +WINAPI +FindFirstStreamW(IN LPCWSTR lpFileName, + IN STREAM_INFO_LEVELS InfoLevel, + OUT LPVOID lpFindStreamData, + IN DWORD dwFlags) +{ + PKERNEL32_FIND_DATA_HEADER IHeader = NULL; + PKERNEL32_FIND_STREAM_DATA IData = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE FileHandle = NULL; + NTSTATUS Status; + ULONG BufferSize = 0; + + if (dwFlags != 0 || InfoLevel != FindStreamInfoStandard || + lpFindStreamData == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + /* validate & translate the filename */ + if (!RtlDosPathNameToNtPathName_U(lpFileName, + &NtPathU, + NULL, + NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return INVALID_HANDLE_VALUE; + } + + /* open the file */ + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtCreateFile(&FileHandle, + 0, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + goto Cleanup; + } + + /* create the search context */ + IHeader = RtlAllocateHeap(hProcessHeap, + 0, + sizeof(KERNEL32_FIND_DATA_HEADER) + + sizeof(KERNEL32_FIND_STREAM_DATA)); + if (IHeader == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + IHeader->Type = StreamFind; + IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1); + + /* capture all information about the streams */ + IData->InfoLevel = InfoLevel; + IData->pCurrent = NULL; + IData->pFileStreamInfo = NULL; + + do + { + BufferSize += 0x1000; + + if (IData->pFileStreamInfo == NULL) + { + IData->pFileStreamInfo = RtlAllocateHeap(hProcessHeap, + 0, + BufferSize); + if (IData->pFileStreamInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + } + else + { + PFILE_STREAM_INFORMATION pfsi; + + pfsi = RtlReAllocateHeap(hProcessHeap, + 0, + IData->pFileStreamInfo, + BufferSize); + if (pfsi == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + IData->pFileStreamInfo = pfsi; + } + + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + IData->pFileStreamInfo, + BufferSize, + FileStreamInformation); + + } while (Status == STATUS_BUFFER_TOO_SMALL); + + if (NT_SUCCESS(Status)) + { + NtClose(FileHandle); + FileHandle = NULL; + + /* select the first stream and return the information */ + IData->pCurrent = IData->pFileStreamInfo; + InternalCopyStreamInfo(IData, + lpFindStreamData); + + /* all done */ + Status = STATUS_SUCCESS; + } + +Cleanup: + if (FileHandle != NULL) + { + NtClose(FileHandle); + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + if (IHeader != NULL) + { + if (IData->pFileStreamInfo != NULL) + { + RtlFreeHeap(hProcessHeap, + 0, + IData->pFileStreamInfo); + } + + RtlFreeHeap(hProcessHeap, + 0, + IHeader); + } + + BaseSetLastNTError(Status); + return INVALID_HANDLE_VALUE; + } + + return (HANDLE)IHeader; +} + + +/* + * @implemented + */ +BOOL +WINAPI +FindNextStreamW(IN HANDLE hFindStream, + OUT LPVOID lpFindStreamData) +{ + PKERNEL32_FIND_DATA_HEADER IHeader; + PKERNEL32_FIND_STREAM_DATA IData; + + IHeader = (PKERNEL32_FIND_DATA_HEADER)hFindStream; + if (hFindStream == NULL || hFindStream == INVALID_HANDLE_VALUE || + IHeader->Type != StreamFind) + { + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + IData = (PKERNEL32_FIND_STREAM_DATA)(IHeader + 1); + + /* select next stream if possible */ + if (IData->pCurrent->NextEntryOffset != 0) + { + IData->pCurrent = (PFILE_STREAM_INFORMATION)((ULONG_PTR)IData->pFileStreamInfo + + IData->pCurrent->NextEntryOffset); + } + else + { + SetLastError(ERROR_HANDLE_EOF); + return FALSE; + } + + /* return the information */ + InternalCopyStreamInfo(IData, + lpFindStreamData); + + return TRUE; +} + + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/hardlink.c b/dll/win32/kernel32/client/file/hardlink.c new file mode 100644 index 00000000000..91e2a6ac674 --- /dev/null +++ b/dll/win32/kernel32/client/file/hardlink.c @@ -0,0 +1,224 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/hardlink.c + * PURPOSE: Hardlink functions + * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net) + * UPDATE HISTORY: + * Created 13/03/2004 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* FUNCTIONS ****************************************************************/ + + +/* + * @implemented + */ +BOOL WINAPI +CreateHardLinkW(LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + UNICODE_STRING LinkTarget, LinkName; + LPVOID lpSecurityDescriptor; + PFILE_LINK_INFORMATION LinkInformation; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + BOOL Ret = FALSE; + + if(!lpFileName || !lpExistingFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + lpSecurityDescriptor = (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL); + + if(RtlDetermineDosPathNameType_U((LPWSTR)lpFileName) == 1 || + RtlDetermineDosPathNameType_U((LPWSTR)lpExistingFileName) == 1) + { + WARN("CreateHardLinkW() cannot handle UNC Paths!\n"); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + if(RtlDosPathNameToNtPathName_U(lpExistingFileName, &LinkTarget, NULL, NULL)) + { + ULONG NeededSize = RtlGetFullPathName_U((LPWSTR)lpExistingFileName, 0, NULL, NULL); + if(NeededSize > 0) + { + LPWSTR lpNtLinkTarget = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize * sizeof(WCHAR)); + if(lpNtLinkTarget != NULL) + { + LPWSTR lpFilePart; + + if(RtlGetFullPathName_U((LPWSTR)lpExistingFileName, NeededSize, lpNtLinkTarget, &lpFilePart) && + (*lpNtLinkTarget) != L'\0') + { + UNICODE_STRING CheckDrive, LinkDrive; + WCHAR wCheckDrive[10]; + + swprintf(wCheckDrive, L"\\??\\%c:", (WCHAR)(*lpNtLinkTarget)); + RtlInitUnicodeString(&CheckDrive, wCheckDrive); + + RtlZeroMemory(&LinkDrive, sizeof(UNICODE_STRING)); + + LinkDrive.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PATH + 1) * sizeof(WCHAR)); + if(LinkDrive.Buffer != NULL) + { + HANDLE hFile, hTarget; + OBJECT_ATTRIBUTES ObjectAttributes; + + InitializeObjectAttributes(&ObjectAttributes, + &CheckDrive, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject(&hFile, 1, &ObjectAttributes); + if(NT_SUCCESS(Status)) + { + UNICODE_STRING LanManager; + + RtlInitUnicodeString(&LanManager, L"\\Device\\LanmanRedirector\\"); + + NtQuerySymbolicLinkObject(hFile, &LinkDrive, NULL); + + if(!RtlPrefixUnicodeString(&LanManager, &LinkDrive, TRUE)) + { + InitializeObjectAttributes(&ObjectAttributes, + &LinkTarget, + OBJ_CASE_INSENSITIVE, + NULL, + lpSecurityDescriptor); + Status = NtOpenFile(&hTarget, + SYNCHRONIZE | DELETE, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT); + if(NT_SUCCESS(Status)) + { + if(RtlDosPathNameToNtPathName_U(lpFileName, &LinkName, NULL, NULL)) + { + NeededSize = sizeof(FILE_LINK_INFORMATION) + LinkName.Length + sizeof(WCHAR); + LinkInformation = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize); + if(LinkInformation != NULL) + { + LinkInformation->ReplaceIfExists = FALSE; + LinkInformation->RootDirectory = 0; + LinkInformation->FileNameLength = LinkName.Length; + RtlCopyMemory(LinkInformation->FileName, LinkName.Buffer, LinkName.Length); + + Status = NtSetInformationFile(hTarget, &IoStatus, LinkInformation, NeededSize, FileLinkInformation); + if(NT_SUCCESS(Status)) + { + Ret = TRUE; + } + else + { + BaseSetLastNTError(Status); + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkInformation); + } + else + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + } + else + { + SetLastError(ERROR_PATH_NOT_FOUND); + } + NtClose(hTarget); + } + else + { + WARN("Unable to open link destination \"%wZ\"!\n", &LinkTarget); + BaseSetLastNTError(Status); + } + } + else + { + WARN("Path \"%wZ\" must not be a mapped drive!\n", &LinkDrive); + SetLastError(ERROR_INVALID_NAME); + } + + NtClose(hFile); + } + else + { + BaseSetLastNTError(Status); + } + } + else + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + } + else + { + SetLastError(ERROR_INVALID_NAME); + } + RtlFreeHeap(RtlGetProcessHeap(), 0, lpNtLinkTarget); + } + else + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + } + else + { + SetLastError(ERROR_INVALID_NAME); + } + RtlFreeHeap(RtlGetProcessHeap(), 0, LinkTarget.Buffer); + } + else + { + SetLastError(ERROR_PATH_NOT_FOUND); + } + + return Ret; +} + + +/* + * @implemented + */ +BOOL WINAPI +CreateHardLinkA(LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + PWCHAR FileNameW, ExistingFileNameW; + BOOL Ret; + + if(!lpFileName || !lpExistingFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return FALSE; + + if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, TRUE))) + return FALSE; + + Ret = CreateHardLinkW(FileNameW , ExistingFileNameW , lpSecurityAttributes); + + RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW); + + return Ret; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/iocompl.c b/dll/win32/kernel32/client/file/iocompl.c new file mode 100644 index 00000000000..462d2a26cbb --- /dev/null +++ b/dll/win32/kernel32/client/file/iocompl.c @@ -0,0 +1,219 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/iocompl.c + * PURPOSE: Io Completion functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#define NDEBUG +#include + +#define NANOS_TO_100NS(nanos) (((LONGLONG)(nanos)) / 100) +#define MICROS_TO_100NS(micros) (((LONGLONG)(micros)) * NANOS_TO_100NS(1000)) +#define MILLIS_TO_100NS(milli) (((LONGLONG)(milli)) * MICROS_TO_100NS(1000)) + +/* + * @implemented + */ +HANDLE +WINAPI +CreateIoCompletionPort( + HANDLE FileHandle, + HANDLE ExistingCompletionPort, + ULONG_PTR CompletionKey, + DWORD NumberOfConcurrentThreads + ) +{ + HANDLE CompletionPort = NULL; + NTSTATUS errCode; + FILE_COMPLETION_INFORMATION CompletionInformation; + IO_STATUS_BLOCK IoStatusBlock; + + if ( FileHandle == INVALID_HANDLE_VALUE && ExistingCompletionPort != NULL ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ( ExistingCompletionPort != NULL ) + { + CompletionPort = ExistingCompletionPort; + } + else + { + + errCode = NtCreateIoCompletion(&CompletionPort, + IO_COMPLETION_ALL_ACCESS, + NULL,//ObjectAttributes + NumberOfConcurrentThreads); + + if (!NT_SUCCESS(errCode) ) + { + BaseSetLastNTError (errCode); + return FALSE; + } + + } + + if ( FileHandle != INVALID_HANDLE_VALUE ) + { + CompletionInformation.Port = CompletionPort; + CompletionInformation.Key = (PVOID)CompletionKey; + + errCode = NtSetInformationFile(FileHandle, + &IoStatusBlock, + &CompletionInformation, + sizeof(FILE_COMPLETION_INFORMATION), + FileCompletionInformation); + + if ( !NT_SUCCESS(errCode) ) + { + if ( ExistingCompletionPort == NULL ) + { + NtClose(CompletionPort); + } + + BaseSetLastNTError (errCode); + return FALSE; + } + } + + return CompletionPort; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetQueuedCompletionStatus( + HANDLE CompletionHandle, + LPDWORD lpNumberOfBytesTransferred, + PULONG_PTR lpCompletionKey, + LPOVERLAPPED *lpOverlapped, + DWORD dwMilliseconds + ) +{ + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatus; + ULONG_PTR CompletionKey; + LARGE_INTEGER Time; + PLARGE_INTEGER TimePtr; + + if (!lpNumberOfBytesTransferred || !lpCompletionKey || !lpOverlapped) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Convert the timeout */ + TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); + + errCode = NtRemoveIoCompletion(CompletionHandle, + (PVOID*)&CompletionKey, + (PVOID*)lpOverlapped, + &IoStatus, + TimePtr); + + if (!NT_SUCCESS(errCode) || errCode == STATUS_TIMEOUT) { + *lpOverlapped = NULL; + BaseSetLastNTError(errCode); + return FALSE; + } + + *lpCompletionKey = CompletionKey; + *lpNumberOfBytesTransferred = IoStatus.Information; + + if (!NT_SUCCESS(IoStatus.Status)){ + //failed io operation + BaseSetLastNTError(IoStatus.Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +PostQueuedCompletionStatus( + HANDLE CompletionHandle, + DWORD dwNumberOfBytesTransferred, + ULONG_PTR dwCompletionKey, + LPOVERLAPPED lpOverlapped + ) +{ + NTSTATUS errCode; + + errCode = NtSetIoCompletion(CompletionHandle, + (PVOID)dwCompletionKey, // KeyContext + (PVOID)lpOverlapped, // ApcContext + STATUS_SUCCESS, // IoStatusBlock->Status + dwNumberOfBytesTransferred); // IoStatusBlock->Information + + if ( !NT_SUCCESS(errCode) ) + { + BaseSetLastNTError (errCode); + return FALSE; + } + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +CancelIo(HANDLE hFile) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + Status = NtCancelIoFile(hFile, + &IoStatusBlock); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return(FALSE); + } + + return(TRUE); +} + + +/* + * @implemented + */ +BOOL +WINAPI +BindIoCompletionCallback(HANDLE FileHandle, + LPOVERLAPPED_COMPLETION_ROUTINE Function, + ULONG Flags) +{ + NTSTATUS Status = 0; + + DPRINT("(%p, %p, %d)\n", FileHandle, Function, Flags); + + Status = RtlSetIoCompletionCallback(FileHandle, + (PIO_APC_ROUTINE)Function, + Flags); + + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/lfile.c b/dll/win32/kernel32/client/file/lfile.c new file mode 100644 index 00000000000..7c1a6b9a2bb --- /dev/null +++ b/dll/win32/kernel32/client/file/lfile.c @@ -0,0 +1,158 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/lfile.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#define NDEBUG +#include + +/* + * @implemented + */ +long +WINAPI +_hread(HFILE hFile, LPVOID lpBuffer, long lBytes) +{ + DWORD NumberOfBytesRead; + + if (!ReadFile(LongToHandle(hFile), + lpBuffer, + (DWORD) lBytes, + &NumberOfBytesRead, + NULL)) + { + return HFILE_ERROR; + } + return NumberOfBytesRead; +} + + +/* + * @implemented + */ +long +WINAPI +_hwrite(HFILE hFile, LPCSTR lpBuffer, long lBytes) +{ + DWORD NumberOfBytesWritten; + + if (lBytes == 0) + { + if (!SetEndOfFile((HANDLE) hFile)) + { + return HFILE_ERROR; + } + return 0; + } + if (!WriteFile(LongToHandle(hFile), + (LPVOID) lpBuffer, + (DWORD) lBytes, + &NumberOfBytesWritten, + NULL)) + { + return HFILE_ERROR; + } + return NumberOfBytesWritten; +} + + +/* + * @implemented + */ +HFILE +WINAPI +_lopen(LPCSTR lpPathName, int iReadWrite) +{ + DWORD dwAccess, dwSharing, dwCreation; + + if (iReadWrite & OF_CREATE) + { + dwCreation = CREATE_ALWAYS; + dwAccess = GENERIC_READ | GENERIC_WRITE; + } + else + { + dwCreation = OPEN_EXISTING; + switch(iReadWrite & 0x03) + { + case OF_READ: dwAccess = GENERIC_READ; break; + case OF_WRITE: dwAccess = GENERIC_WRITE; break; + case OF_READWRITE: dwAccess = GENERIC_READ | GENERIC_WRITE; break; + default: dwAccess = 0; break; + } + } + + switch(iReadWrite & 0x70) + { + case OF_SHARE_EXCLUSIVE: dwSharing = 0; break; + case OF_SHARE_DENY_WRITE: dwSharing = FILE_SHARE_READ; break; + case OF_SHARE_DENY_READ: dwSharing = FILE_SHARE_WRITE; break; + case OF_SHARE_DENY_NONE: + case OF_SHARE_COMPAT: + default: dwSharing = FILE_SHARE_READ | FILE_SHARE_WRITE; break; + } + + return (HFILE) CreateFileA(lpPathName, + dwAccess, + dwSharing, + NULL, + dwCreation, + FILE_ATTRIBUTE_NORMAL, + NULL); +} + + +/* + * @implemented + */ +HFILE +WINAPI +_lcreat(LPCSTR lpPathName, int iAttribute) +{ + HANDLE hFile; + + iAttribute &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; + hFile = CreateFileA(lpPathName, + GENERIC_READ | GENERIC_WRITE, + (FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, + CREATE_ALWAYS, + iAttribute, + NULL); + + return HandleToLong(hFile); +} + + +/* + * @implemented + */ +int +WINAPI +_lclose(HFILE hFile) +{ + return CloseHandle(LongToHandle(hFile)) ? 0 : HFILE_ERROR; +} + + +/* + * @implemented + */ +LONG +WINAPI +_llseek(HFILE hFile, LONG lOffset, int iOrigin) +{ + return SetFilePointer(LongToHandle(hFile), + lOffset, + NULL, + (DWORD) iOrigin); +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/lock.c b/dll/win32/kernel32/client/file/lock.c new file mode 100644 index 00000000000..df3a6f2c125 --- /dev/null +++ b/dll/win32/kernel32/client/file/lock.c @@ -0,0 +1,190 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/file/lock.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* FIXME: the large integer manipulations in this file dont handle overflow */ + +/* INCLUDES ****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +LockFile(HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh) +{ + DWORD dwReserved; + OVERLAPPED Overlapped; + + Overlapped.Offset = dwFileOffsetLow; + Overlapped.OffsetHigh = dwFileOffsetHigh; + Overlapped.hEvent = NULL; + dwReserved = 0; + + return LockFileEx(hFile, + LOCKFILE_FAIL_IMMEDIATELY | + LOCKFILE_EXCLUSIVE_LOCK, + dwReserved, + nNumberOfBytesToLockLow, + nNumberOfBytesToLockHigh, + &Overlapped ) ; +} + + +/* + * @implemented + */ +BOOL +WINAPI +LockFileEx(HANDLE hFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped /* required! */) +{ + LARGE_INTEGER BytesToLock; + BOOL LockImmediate; + BOOL LockExclusive; + NTSTATUS errCode; + LARGE_INTEGER Offset; + + if(dwReserved != 0 || lpOverlapped==NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + TRACE( "%p %x%08x %x%08x flags %x\n", + hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset, + nNumberOfBytesToLockHigh, nNumberOfBytesToLockLow, dwFlags ); + + lpOverlapped->Internal = STATUS_PENDING; + + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + + if ( (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) == LOCKFILE_FAIL_IMMEDIATELY ) + LockImmediate = TRUE; + else + LockImmediate = FALSE; + + if ( (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) == LOCKFILE_EXCLUSIVE_LOCK ) + LockExclusive = TRUE; + else + LockExclusive = FALSE; + + BytesToLock.u.LowPart = nNumberOfBytesToLockLow; + BytesToLock.u.HighPart = nNumberOfBytesToLockHigh; + + errCode = NtLockFile(hFile, + lpOverlapped->hEvent, + NULL, + NULL, + (PIO_STATUS_BLOCK)lpOverlapped, + &Offset, + &BytesToLock, + 0, + (BOOLEAN)LockImmediate, + (BOOLEAN)LockExclusive); + + if ( !NT_SUCCESS(errCode) ) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +UnlockFile(HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh) +{ + OVERLAPPED Overlapped; + DWORD dwReserved; + Overlapped.Offset = dwFileOffsetLow; + Overlapped.OffsetHigh = dwFileOffsetHigh; + dwReserved = 0; + + return UnlockFileEx(hFile, + dwReserved, + nNumberOfBytesToUnlockLow, + nNumberOfBytesToUnlockHigh, + &Overlapped); +} + + +/* + * @implemented + */ +BOOL +WINAPI +UnlockFileEx(HANDLE hFile, + DWORD dwReserved, + DWORD nNumberOfBytesToUnLockLow, + DWORD nNumberOfBytesToUnLockHigh, + LPOVERLAPPED lpOverlapped /* required! */) +{ + LARGE_INTEGER BytesToUnLock; + LARGE_INTEGER StartAddress; + NTSTATUS errCode; + + if(dwReserved != 0 || lpOverlapped == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + TRACE( "%p %x%08x %x%08x\n", + hFile, lpOverlapped->OffsetHigh, lpOverlapped->Offset, + nNumberOfBytesToUnLockHigh, nNumberOfBytesToUnLockLow); + + BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow; + BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh; + + StartAddress.u.LowPart = lpOverlapped->Offset; + StartAddress.u.HighPart = lpOverlapped->OffsetHigh; + + errCode = NtUnlockFile(hFile, + (PIO_STATUS_BLOCK)lpOverlapped, + &StartAddress, + &BytesToUnLock, + 0); + + if ( !NT_SUCCESS(errCode) ) + { + BaseSetLastNTError(errCode); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/mailslot.c b/dll/win32/kernel32/client/file/mailslot.c new file mode 100644 index 00000000000..d0895e5dfbe --- /dev/null +++ b/dll/win32/kernel32/client/file/mailslot.c @@ -0,0 +1,223 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/mailslot.c + * PURPOSE: Mailslot functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +HANDLE WINAPI +CreateMailslotA(LPCSTR lpName, + DWORD nMaxMessageSize, + DWORD lReadTimeout, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + HANDLE MailslotHandle; + UNICODE_STRING NameU; + ANSI_STRING NameA; + + RtlInitAnsiString(&NameA, (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE); + + MailslotHandle = CreateMailslotW(NameU.Buffer, + nMaxMessageSize, + lReadTimeout, + lpSecurityAttributes); + + RtlFreeUnicodeString(&NameU); + + return(MailslotHandle); +} + + +/* + * @implemented + */ +HANDLE WINAPI +CreateMailslotW(LPCWSTR lpName, + DWORD nMaxMessageSize, + DWORD lReadTimeout, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING MailslotName; + HANDLE MailslotHandle; + NTSTATUS Status; + BOOLEAN Result; + LARGE_INTEGER DefaultTimeOut; + IO_STATUS_BLOCK Iosb; + ULONG Attributes = OBJ_CASE_INSENSITIVE; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + + Result = RtlDosPathNameToNtPathName_U(lpName, + &MailslotName, + NULL, + NULL); + if (!Result) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return(INVALID_HANDLE_VALUE); + } + + TRACE("Mailslot name: %wZ\n", &MailslotName); + + if(lpSecurityAttributes) + { + SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; + if(lpSecurityAttributes->bInheritHandle) + Attributes |= OBJ_INHERIT; + } + + InitializeObjectAttributes(&ObjectAttributes, + &MailslotName, + Attributes, + NULL, + SecurityDescriptor); + + if (lReadTimeout == MAILSLOT_WAIT_FOREVER) + { + /* Set the max */ + DefaultTimeOut.LowPart = 0; + DefaultTimeOut.HighPart = 0x80000000; + } + else + { + /* Convert to NT format */ + DefaultTimeOut.QuadPart = UInt32x32To64(-10000, lReadTimeout); + } + + Status = NtCreateMailslotFile(&MailslotHandle, + GENERIC_READ | SYNCHRONIZE | WRITE_DAC, + &ObjectAttributes, + &Iosb, + FILE_WRITE_THROUGH, + 0, + nMaxMessageSize, + &DefaultTimeOut); + + if (Status == STATUS_INVALID_DEVICE_REQUEST || Status == STATUS_NOT_SUPPORTED) + { + Status = STATUS_OBJECT_NAME_INVALID; + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + MailslotName.Buffer); + + if (!NT_SUCCESS(Status)) + { + WARN("NtCreateMailslot failed (Status %x)!\n", Status); + BaseSetLastNTError (Status); + return(INVALID_HANDLE_VALUE); + } + + return(MailslotHandle); +} + + +/* + * @implemented + */ +BOOL WINAPI +GetMailslotInfo(HANDLE hMailslot, + LPDWORD lpMaxMessageSize, + LPDWORD lpNextSize, + LPDWORD lpMessageCount, + LPDWORD lpReadTimeout) +{ + FILE_MAILSLOT_QUERY_INFORMATION Buffer; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Status = NtQueryInformationFile(hMailslot, + &Iosb, + &Buffer, + sizeof(FILE_MAILSLOT_QUERY_INFORMATION), + FileMailslotQueryInformation); + if (!NT_SUCCESS(Status)) + { + WARN("NtQueryInformationFile failed (Status %x)!\n", Status); + BaseSetLastNTError (Status); + return(FALSE); + } + + if (lpMaxMessageSize != NULL) + { + *lpMaxMessageSize = Buffer.MaximumMessageSize; + } + if (lpNextSize != NULL) + { + *lpNextSize = Buffer.NextMessageSize; + } + if (lpMessageCount != NULL) + { + *lpMessageCount = Buffer.MessagesAvailable; + } + if (lpReadTimeout != NULL) + { + if (Buffer.ReadTimeout.LowPart == 0 && + Buffer.ReadTimeout.HighPart == (LONG)0x80000000) + *lpReadTimeout = MAILSLOT_WAIT_FOREVER; + else + *lpReadTimeout = (DWORD)(Buffer.ReadTimeout.QuadPart / -10000); + } + + return(TRUE); +} + + +/* + * @implemented + */ +BOOL WINAPI +SetMailslotInfo(HANDLE hMailslot, + DWORD lReadTimeout) +{ + FILE_MAILSLOT_SET_INFORMATION Buffer; + LARGE_INTEGER Timeout; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + if (lReadTimeout == MAILSLOT_WAIT_FOREVER) + { + /* Set the max */ + Timeout.LowPart = 0; + Timeout.HighPart = 0x80000000; + } + else + { + /* Convert to NT format */ + Timeout.QuadPart = UInt32x32To64(-10000, lReadTimeout); + } + Buffer.ReadTimeout = &Timeout; + + Status = NtSetInformationFile(hMailslot, + &Iosb, + &Buffer, + sizeof(FILE_MAILSLOT_SET_INFORMATION), + FileMailslotSetInformation); + if (!NT_SUCCESS(Status)) + { + WARN("NtSetInformationFile failed (Status %x)!\n", Status); + BaseSetLastNTError (Status); + return(FALSE); + } + + return(TRUE); +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/move.c b/dll/win32/kernel32/client/file/move.c new file mode 100644 index 00000000000..cfbe5f2dfb5 --- /dev/null +++ b/dll/win32/kernel32/client/file/move.c @@ -0,0 +1,796 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/file.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Gerhard W. Gruber (sparhawk_at_gmx.at) + * Dmitry Philippov (shedon@mail.ru) + * UPDATE HISTORY: + * Created 01/11/98 + * DP (29/07/2006) + * Fix some bugs in the add_boot_rename_entry function + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* GLOBALS *****************************************************************/ + +/* FUNCTIONS ****************************************************************/ +static BOOL +RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName) +{ + DWORD Attributes; + Attributes = GetFileAttributesW(lpFileName); + if (Attributes != INVALID_FILE_ATTRIBUTES) + { + return SetFileAttributesW(lpFileName,Attributes - + (Attributes & ~FILE_ATTRIBUTE_READONLY)); + } + + return FALSE; +} + + +/*********************************************************************** + * add_boot_rename_entry + * + * Adds an entry to the registry that is loaded when windows boots and + * checks if there are some files to be removed or renamed/moved. + * has to be valid and may be NULL. If both pointers are + * non-NULL then the file is moved, otherwise it is deleted. The + * entry of the registrykey is always appended with two zero + * terminated strings. If is NULL then the second entry is + * simply a single 0-byte. Otherwise the second filename goes + * there. The entries are prepended with \??\ before the path and the + * second filename gets also a '!' as the first character if + * MOVEFILE_REPLACE_EXISTING is set. After the final string another + * 0-byte follows to indicate the end of the strings. + * i.e.: + * \??\D:\test\file1[0] + * !\??\D:\test\file1_renamed[0] + * \??\D:\Test|delete[0] + * [0] <- file is to be deleted, second string empty + * \??\D:\test\file2[0] + * !\??\D:\test\file2_renamed[0] + * [0] <- indicates end of strings + * + * or: + * \??\D:\test\file1[0] + * !\??\D:\test\file1_renamed[0] + * \??\D:\Test|delete[0] + * [0] <- file is to be deleted, second string empty + * [0] <- indicates end of strings + * + */ +static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags ) +{ + static const WCHAR ValueName[] = {'P','e','n','d','i','n','g', + 'F','i','l','e','R','e','n','a','m','e', + 'O','p','e','r','a','t','i','o','n','s',0}; + + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager"); + + static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data ); + + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING nameW, source_name, dest_name; + KEY_VALUE_PARTIAL_INFORMATION *info; + BOOL rc = FALSE; + HANDLE Reboot = NULL; + DWORD len1, len2; + DWORD DestLen = 0; + DWORD DataSize = 0; + BYTE *Buffer = NULL; + WCHAR *p; + NTSTATUS Status; + + TRACE("add_boot_rename_entry( %S, %S, %d ) \n", source, dest, flags); + + if(dest) + DestLen = wcslen(dest); + + if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL )) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; + } + dest_name.Buffer = NULL; + if (DestLen && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL )) + { + RtlFreeHeap( RtlGetProcessHeap(), 0, source_name.Buffer ); + SetLastError( ERROR_PATH_NOT_FOUND ); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtCreateKey(&Reboot, + KEY_QUERY_VALUE | KEY_SET_VALUE, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (Status == STATUS_ACCESS_DENIED) + { + Status = NtCreateKey( + &Reboot, + KEY_QUERY_VALUE | KEY_SET_VALUE, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_BACKUP_RESTORE, + NULL); + } + + if (!NT_SUCCESS(Status)) + { + WARN("NtCreateKey() failed (Status 0x%lx)\n", Status); + if (source_name.Buffer) + RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer); + if (dest_name.Buffer) + RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer); + return FALSE; + } + + len1 = source_name.Length + sizeof(WCHAR); + if (DestLen) + { + len2 = dest_name.Length + sizeof(WCHAR); + if (flags & MOVEFILE_REPLACE_EXISTING) + len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */ + } + else + { + len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */ + } + + RtlInitUnicodeString( &nameW, ValueName ); + + /* First we check if the key exists and if so how many bytes it already contains. */ + Status = NtQueryValueKey( + Reboot, + &nameW, + KeyValuePartialInformation, + NULL, + 0, + &DataSize ); + if ((Status == STATUS_BUFFER_OVERFLOW) || + (Status == STATUS_BUFFER_TOO_SMALL)) + { + if (!(Buffer = HeapAlloc(GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR)))) + goto Quit; + Status = NtQueryValueKey(Reboot, &nameW, KeyValuePartialInformation, + Buffer, DataSize, &DataSize); + if(!NT_SUCCESS(Status)) + goto Quit; + info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer; + if (info->Type != REG_MULTI_SZ) goto Quit; + if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR); /* remove terminating null (will be added back later) */ + } + else + { + DataSize = info_size; + if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) ))) + goto Quit; + } + + memcpy( Buffer + DataSize, source_name.Buffer, len1 ); + DataSize += len1; + p = (WCHAR *)(Buffer + DataSize); + if (DestLen) + { + if (flags & MOVEFILE_REPLACE_EXISTING) + *p++ = '!'; + memcpy( p, dest_name.Buffer, len2 ); + DataSize += len2; + } + else + { + *p = 0; + DataSize += sizeof(WCHAR); + } + + /* add final null */ + p = (WCHAR *)(Buffer + DataSize); + *p = 0; + DataSize += sizeof(WCHAR); + + rc = NT_SUCCESS(NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size)); + + Quit: + RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer); + if (dest_name.Buffer) + RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer); + NtClose(Reboot); + if(Buffer) + HeapFree(GetProcessHeap(), 0, Buffer); + return(rc); +} + + +/* + * @implemented + */ +BOOL +WINAPI +MoveFileWithProgressW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags + ) +{ + HANDLE hFile = NULL, hNewFile = NULL; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + PFILE_RENAME_INFORMATION FileRename; + NTSTATUS errCode; + BOOL Result; + UNICODE_STRING DstPathU; + BOOL folder = FALSE; + + TRACE("MoveFileWithProgressW()\n"); + + if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) + return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags ); + +// if (dwFlags & MOVEFILE_WRITE_THROUGH) +// FIXME("MOVEFILE_WRITE_THROUGH unimplemented\n"); + + if (!lpNewFileName) + return DeleteFileW(lpExistingFileName); + + /* validate & translate the filename */ + if (!RtlDosPathNameToNtPathName_U (lpNewFileName, + &DstPathU, + NULL, + NULL)) + { + WARN("Invalid destination path\n"); + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &DstPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + errCode = NtOpenFile( &hNewFile, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | + ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) ); + + if (NT_SUCCESS(errCode)) /* Destination exists */ + { + NtClose(hNewFile); + + if (!(dwFlags & MOVEFILE_REPLACE_EXISTING)) + { + SetLastError(ERROR_ALREADY_EXISTS); + return FALSE; + } + else if (GetFileAttributesW(lpNewFileName) & FILE_ATTRIBUTE_DIRECTORY) + { + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + } + + hFile = CreateFileW (lpExistingFileName, + GENERIC_ALL, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | + ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_FLAG_WRITE_THROUGH : 0), + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + FileRename = RtlAllocateHeap( + RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length); + if( !FileRename ) { + CloseHandle(hFile); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + if( dwFlags & MOVEFILE_REPLACE_EXISTING ) { + FileRename->ReplaceIfExists = TRUE; + } + else { + FileRename->ReplaceIfExists = FALSE; + } + + + memcpy(FileRename->FileName, DstPathU.Buffer, DstPathU.Length); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DstPathU.Buffer); + + FileRename->FileNameLength = DstPathU.Length; + errCode = NtSetInformationFile (hFile, + &IoStatusBlock, + FileRename, + sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length, + FileRenameInformation); + CloseHandle(hFile); + RtlFreeHeap(RtlGetProcessHeap(), 0, FileRename); + + if (GetFileAttributesW(lpExistingFileName) & FILE_ATTRIBUTE_DIRECTORY) + { + folder = TRUE; + } + + + /* + * FIXME: + * Fail now move the folder + * Before we fail at CreateFileW + */ + + + if (NT_SUCCESS(errCode)) + { + Result = TRUE; + } + else + { + if (folder==FALSE) + { + Result = CopyFileExW (lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + NULL, + (dwFlags & MOVEFILE_REPLACE_EXISTING) ? 0 : COPY_FILE_FAIL_IF_EXISTS); + if (Result) + { + /* Cleanup the source file */ + Result = DeleteFileW (lpExistingFileName); + } + } + else + { + /* move folder code start */ + WIN32_FIND_DATAW findBuffer; + LPWSTR lpExistingFileName2 = NULL; + LPWSTR lpNewFileName2 = NULL; + LPWSTR lpDeleteFile = NULL; + INT size; + INT size2; + BOOL loop = TRUE; + BOOL Result = FALSE; + INT max_size = MAX_PATH; + + + /* Build the string */ + size = wcslen(lpExistingFileName); + if (size+6> max_size) + max_size = size + 6; + + lpDeleteFile = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR)); + if (lpDeleteFile == NULL) + return FALSE; + + lpNewFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR)); + if (lpNewFileName2 == NULL) + { + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + return FALSE; + } + + lpExistingFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR)); + if (lpExistingFileName2 == NULL) + { + HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + return FALSE; + } + + wcscpy( (WCHAR *)lpExistingFileName2,lpExistingFileName); + wcscpy( (WCHAR *)&lpExistingFileName2[size],L"\\*.*\0"); + + /* Get the file name */ + memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW)); + hFile = FindFirstFileW(lpExistingFileName2, &findBuffer); + if (hFile == INVALID_HANDLE_VALUE) + loop=FALSE; + + if (findBuffer.cFileName[0] == L'\0') + loop=FALSE; + + + /* FIXME + * remove readonly flag from source folder and do not set the readonly flag to dest folder + */ + RemoveReadOnlyAttributeW(lpExistingFileName); + RemoveReadOnlyAttributeW(lpNewFileName); + //CreateDirectoryExW(lpExistingFileName,lpNewFileName,NULL); + CreateDirectoryW(lpNewFileName, NULL); + + /* search the files/folders and move them */ + while (loop==TRUE) + { + Result = TRUE; + + if ((!wcscmp(findBuffer.cFileName,L"..")) || (!wcscmp(findBuffer.cFileName,L"."))) + { + loop = FindNextFileW(hFile, &findBuffer); + + if (!loop) + { + size = wcslen(lpExistingFileName2)-4; + FindClose(hFile); + hFile = INVALID_HANDLE_VALUE; + + wcscpy( &lpExistingFileName2[size],L"\0"); + + if (wcsncmp(lpExistingFileName,lpExistingFileName2,size)) + { + DWORD Attributes; + + /* delete folder */ + TRACE("MoveFileWithProgressW : Delete folder : %S\n",lpDeleteFile); + + /* remove system folder flag other wise we can not delete the folder */ + Attributes = GetFileAttributesW(lpExistingFileName2); + if (Attributes != INVALID_FILE_ATTRIBUTES) + { + SetFileAttributesW(lpExistingFileName2,(Attributes & ~FILE_ATTRIBUTE_SYSTEM)); + } + + RemoveReadOnlyAttributeW(lpExistingFileName2); + + Result = RemoveDirectoryW(lpExistingFileName2); + if (Result == FALSE) + break; + + loop=TRUE; + size = wcslen(lpExistingFileName); + + if (size+6>max_size) + { + if (lpNewFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); + + if (lpExistingFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); + + if (lpDeleteFile != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + + return FALSE; + } + + wcscpy( lpExistingFileName2,lpExistingFileName); + wcscpy( &lpExistingFileName2[size],L"\\*.*\0"); + + /* Get the file name */ + memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW)); + hFile = FindFirstFileW(lpExistingFileName2, &findBuffer); + } + } + continue; + } + + if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + + /* Build the new src string */ + size = wcslen(findBuffer.cFileName); + size2= wcslen(lpExistingFileName2); + + if (size2+size+6>max_size) + { + FindClose(hFile); + + if (lpNewFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); + + if (lpExistingFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); + + if (lpDeleteFile != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + + return FALSE; + } + + wcscpy( &lpExistingFileName2[size2-3],findBuffer.cFileName); + wcscpy( &lpExistingFileName2[size2+size-3],L"\0"); + + + /* Continue */ + wcscpy( lpDeleteFile,lpExistingFileName2); + wcscpy( &lpExistingFileName2[size2+size-3],L"\\*.*\0"); + + + /* Build the new dst string */ + size = wcslen(lpExistingFileName2) + wcslen(lpNewFileName); + size2 = wcslen(lpExistingFileName); + + if (size>max_size) + { + FindClose(hFile); + + if (lpNewFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); + + if (lpExistingFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); + + if (lpDeleteFile != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + + return FALSE; + } + + wcscpy( lpNewFileName2,lpNewFileName); + size = wcslen(lpNewFileName); + wcscpy( &lpNewFileName2[size], &lpExistingFileName2[size2]); + size = wcslen(lpNewFileName2); + wcscpy( &lpNewFileName2[size-4],L"\0"); + + /* Create Folder */ + + /* FIXME + * remove readonly flag from source folder and do not set the readonly flag to dest folder + */ + RemoveReadOnlyAttributeW(lpDeleteFile); + RemoveReadOnlyAttributeW(lpNewFileName2); + + CreateDirectoryW(lpNewFileName2,NULL); + //CreateDirectoryExW(lpDeleteFile, lpNewFileName2,NULL); + + + /* set new search path from src string */ + FindClose(hFile); + memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW)); + hFile = FindFirstFileW(lpExistingFileName2, &findBuffer); + } + else + { + + /* Build the new string */ + size = wcslen(findBuffer.cFileName); + size2= wcslen(lpExistingFileName2); + wcscpy( lpDeleteFile,lpExistingFileName2); + wcscpy( &lpDeleteFile[size2-3],findBuffer.cFileName); + + /* Build dest string */ + size = wcslen(lpDeleteFile) + wcslen(lpNewFileName); + size2 = wcslen(lpExistingFileName); + + if (size>max_size) + { + FindClose(hFile); + + if (lpNewFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); + + if (lpExistingFileName2 != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); + + if (lpDeleteFile != NULL) + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + + return FALSE; + } + + wcscpy( lpNewFileName2,lpNewFileName); + size = wcslen(lpNewFileName); + wcscpy(&lpNewFileName2[size],&lpDeleteFile[size2]); + + + /* overrite existsen file, if the file got the flag have readonly + * we need reomve that flag + */ + + /* copy file */ + + TRACE("MoveFileWithProgressW : Copy file : %S to %S\n",lpDeleteFile, lpNewFileName2); + RemoveReadOnlyAttributeW(lpDeleteFile); + RemoveReadOnlyAttributeW(lpNewFileName2); + + Result = CopyFileExW (lpDeleteFile, + lpNewFileName2, + lpProgressRoutine, + lpData, + NULL, + 0); + + if (Result == FALSE) + break; + + /* delete file */ + TRACE("MoveFileWithProgressW : remove readonly flag from file : %S\n",lpNewFileName2); + Result = RemoveReadOnlyAttributeW(lpDeleteFile); + if (Result == FALSE) + break; + + TRACE("MoveFileWithProgressW : Delete file : %S\n",lpDeleteFile); + Result = DeleteFileW(lpDeleteFile); + if (Result == FALSE) + break; + + } + loop = FindNextFileW(hFile, &findBuffer); + } + + + /* Remove last folder */ + if ((loop == FALSE) && (Result != FALSE)) + { + DWORD Attributes; + + Attributes = GetFileAttributesW(lpDeleteFile); + if (Attributes != INVALID_FILE_ATTRIBUTES) + { + SetFileAttributesW(lpDeleteFile,(Attributes & ~FILE_ATTRIBUTE_SYSTEM)); + } + + Result = RemoveDirectoryW(lpExistingFileName); + } + + /* Cleanup */ + FindClose(hFile); + + if (lpNewFileName2 != NULL) + { + HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); + lpNewFileName2 = NULL; + } + + if (lpExistingFileName2 != NULL) + { + HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); + lpExistingFileName2 = NULL; + } + + if (lpDeleteFile != NULL) + { + HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); + lpDeleteFile = NULL; + } + + return Result; + + // end move folder code + } + } + + + return Result; +} + + +/* + * @implemented + */ +BOOL +WINAPI +MoveFileWithProgressA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags + ) +{ + PWCHAR ExistingFileNameW; + PWCHAR NewFileNameW; + BOOL ret; + + if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, FALSE))) + return FALSE; + + if (!(NewFileNameW= FilenameA2W(lpNewFileName, TRUE))) + return FALSE; + + ret = MoveFileWithProgressW (ExistingFileNameW , + NewFileNameW, + lpProgressRoutine, + lpData, + dwFlags); + + RtlFreeHeap (RtlGetProcessHeap (), 0, NewFileNameW); + + return ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +MoveFileW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName + ) +{ + return MoveFileExW (lpExistingFileName, + lpNewFileName, + MOVEFILE_COPY_ALLOWED); +} + + +/* + * @implemented + */ +BOOL +WINAPI +MoveFileExW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + DWORD dwFlags + ) +{ + return MoveFileWithProgressW (lpExistingFileName, + lpNewFileName, + NULL, + NULL, + dwFlags); +} + + +/* + * @implemented + */ +BOOL +WINAPI +MoveFileA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName + ) +{ + return MoveFileExA (lpExistingFileName, + lpNewFileName, + MOVEFILE_COPY_ALLOWED); +} + + +/* + * @implemented + */ +BOOL +WINAPI +MoveFileExA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + DWORD dwFlags + ) +{ + return MoveFileWithProgressA (lpExistingFileName, + lpNewFileName, + NULL, + NULL, + dwFlags); +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/npipe.c b/dll/win32/kernel32/client/file/npipe.c new file mode 100644 index 00000000000..35410a19972 --- /dev/null +++ b/dll/win32/kernel32/client/file/npipe.c @@ -0,0 +1,1264 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Win32 Kernel Library + * FILE: lib/kernel32/file/npipe.c + * PURPOSE: Named Pipe Functions + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * Ariadne ( ariadne@xs4all.nl) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +//#define USING_PROPER_NPFS_WAIT_SEMANTICS + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +HANDLE +WINAPI +CreateNamedPipeA(LPCSTR lpName, + DWORD dwOpenMode, + DWORD dwPipeMode, + DWORD nMaxInstances, + DWORD nOutBufferSize, + DWORD nInBufferSize, + DWORD nDefaultTimeOut, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + /* Call the W(ide) function */ + ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe, + lpName, + dwOpenMode, + dwPipeMode, + nMaxInstances, + nOutBufferSize, + nInBufferSize, + nDefaultTimeOut, + lpSecurityAttributes); +} + + +/* + * @implemented + */ +HANDLE +WINAPI +CreateNamedPipeW(LPCWSTR lpName, + DWORD dwOpenMode, + DWORD dwPipeMode, + DWORD nMaxInstances, + DWORD nOutBufferSize, + DWORD nInBufferSize, + DWORD nDefaultTimeOut, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + UNICODE_STRING NamedPipeName; + BOOL Result; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE PipeHandle; + ACCESS_MASK DesiredAccess; + ULONG CreateOptions = 0; + ULONG WriteModeMessage; + ULONG ReadModeMessage; + ULONG NonBlocking; + IO_STATUS_BLOCK Iosb; + ULONG ShareAccess = 0, Attributes; + LARGE_INTEGER DefaultTimeOut; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + + /* Check for valid instances */ + if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + /* Convert to NT syntax */ + if (nMaxInstances == PIPE_UNLIMITED_INSTANCES) + nMaxInstances = -1; + + /* Convert the name */ + Result = RtlDosPathNameToNtPathName_U(lpName, + &NamedPipeName, + NULL, + NULL); + if (!Result) + { + /* Conversion failed */ + SetLastError(ERROR_PATH_NOT_FOUND); + return INVALID_HANDLE_VALUE; + } + + TRACE("Pipe name: %wZ\n", &NamedPipeName); + TRACE("Pipe name: %S\n", NamedPipeName.Buffer); + + /* Always case insensitive, check if we got extra attributes */ + Attributes = OBJ_CASE_INSENSITIVE; + if(lpSecurityAttributes) + { + /* We did; get the security descriptor */ + SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; + + /* And check if this is pipe's handle will beinheritable */ + if (lpSecurityAttributes->bInheritHandle) + Attributes |= OBJ_INHERIT; + } + + /* Now we can initialize the object attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &NamedPipeName, + Attributes, + NULL, + SecurityDescriptor); + + /* Setup the default Desired Access */ + DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC | + WRITE_OWNER | + ACCESS_SYSTEM_SECURITY)); + + /* Convert to NT Create Flags */ + if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) + { + CreateOptions |= FILE_WRITE_THROUGH; + } + + if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) + { + CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; + } + + /* Handle all open modes */ + if (dwOpenMode & PIPE_ACCESS_OUTBOUND) + { + ShareAccess |= FILE_SHARE_READ; + DesiredAccess |= GENERIC_WRITE; + } + + if (dwOpenMode & PIPE_ACCESS_INBOUND) + { + ShareAccess |= FILE_SHARE_WRITE; + DesiredAccess |= GENERIC_READ; + } + + /* Handle the type flags */ + if (dwPipeMode & PIPE_TYPE_MESSAGE) + { + WriteModeMessage = FILE_PIPE_MESSAGE_TYPE; + } + else + { + WriteModeMessage = FILE_PIPE_BYTE_STREAM_TYPE; + } + + /* Handle the mode flags */ + if (dwPipeMode & PIPE_READMODE_MESSAGE) + { + ReadModeMessage = FILE_PIPE_MESSAGE_MODE; + } + else + { + ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE; + } + + /* Handle the blocking mode */ + if (dwPipeMode & PIPE_NOWAIT) + { + NonBlocking = FILE_PIPE_COMPLETE_OPERATION; + } + else + { + NonBlocking = FILE_PIPE_QUEUE_OPERATION; + } + + /* Check if we have a timeout */ + if (nDefaultTimeOut) + { + /* Convert the time to NT format */ + DefaultTimeOut.QuadPart = UInt32x32To64(nDefaultTimeOut, -10000); + } + else + { + /* Use default timeout of 50 ms */ + DefaultTimeOut.QuadPart = -500000; + } + + /* Now create the pipe */ + Status = NtCreateNamedPipeFile(&PipeHandle, + DesiredAccess, + &ObjectAttributes, + &Iosb, + ShareAccess, + FILE_OPEN_IF, + CreateOptions, + WriteModeMessage, + ReadModeMessage, + NonBlocking, + nMaxInstances, + nInBufferSize, + nOutBufferSize, + &DefaultTimeOut); + + /* Normalize special error codes */ + if ((Status == STATUS_INVALID_DEVICE_REQUEST) || + (Status == STATUS_NOT_SUPPORTED)) + { + Status = STATUS_OBJECT_NAME_INVALID; + } + + /* Free the name */ + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NamedPipeName.Buffer); + + /* Check status */ + if (!NT_SUCCESS(Status)) + { + /* Failed to create it */ + WARN("NtCreateNamedPipe failed (Status %x)!\n", Status); + BaseSetLastNTError (Status); + return INVALID_HANDLE_VALUE; + } + + /* Return the handle */ + return PipeHandle; +} + + +/* + * @implemented + */ +BOOL +WINAPI +WaitNamedPipeA(LPCSTR lpNamedPipeName, + DWORD nTimeOut) +{ + BOOL r; + UNICODE_STRING NameU; + + /* Convert the name to Unicode */ + Basep8BitStringToDynamicUnicodeString(&NameU, lpNamedPipeName); + + /* Call the Unicode API */ + r = WaitNamedPipeW(NameU.Buffer, nTimeOut); + + /* Free the Unicode string */ + RtlFreeUnicodeString(&NameU); + + /* Return result */ + return r; +} + + +/* + * When NPFS will work properly, use this code instead. It is compatible with + * Microsoft's NPFS.SYS. The main difference is that: + * - This code actually respects the timeout instead of ignoring it! + * - This code validates and creates the proper names for both UNC and local pipes + * - On NT, you open the *root* pipe directory (either \DosDevices\Pipe or + * \DosDevices\Unc\Server\Pipe) and then send the pipe to wait on in the + * FILE_PIPE_WAIT_FOR_BUFFER structure. + */ +#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS +/* + * @implemented + */ +BOOL +WINAPI +WaitNamedPipeW(LPCWSTR lpNamedPipeName, + DWORD nTimeOut) +{ + UNICODE_STRING NamedPipeName, NewName, DevicePath, PipePrefix; + ULONG NameLength; + ULONG i; + PWCHAR p; + ULONG Type; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE FileHandle; + IO_STATUS_BLOCK IoStatusBlock; + ULONG WaitPipeInfoSize; + PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo; + + /* Start by making a unicode string of the name */ + TRACE("Sent path: %S\n", lpNamedPipeName); + RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName); + NameLength = NamedPipeName.Length / sizeof(WCHAR); + + /* All slashes must become backslashes */ + for (i = 0; i < NameLength; i++) + { + /* Check and convert */ + if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\'; + } + + /* Find the path type of the name we were given */ + NewName = NamedPipeName; + Type = RtlDetermineDosPathNameType_U(lpNamedPipeName); + + /* Check if this was a device path, ie : "\\.\pipe\name" */ + if (Type == RtlPathTypeLocalDevice) + { + /* Make sure it's a valid prefix */ + RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\"); + RtlPrefixString((PANSI_STRING)&PipePrefix, (PANSI_STRING)&NewName, TRUE); + + /* Move past it */ + NewName.Buffer += 9; + NewName.Length -= 9 * sizeof(WCHAR); + + /* Initialize the Dos Devices name */ + TRACE("NewName: %wZ\n", &NewName); + RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\"); + } + else if (Type == RtlPathTypeRootLocalDevice) + { + /* The path is \\server\\pipe\name; find the pipename itself */ + p = &NewName.Buffer[2]; + + /* First loop to get past the server name */ + do + { + /* Check if this is a backslash */ + if (*p == L'\\') break; + + /* Check next */ + p++; + } while (*p); + + /* Now make sure the full name contains "pipe\" */ + if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\")))) + { + /* Get to the pipe name itself now */ + p += sizeof("pipe\\") - 1; + } + else + { + /* The name is invalid */ + WARN("Invalid name!\n"); + BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); + return FALSE; + } + + /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */ + } + else + { + WARN("Invalid path type\n"); + BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); + return FALSE; + } + + /* Now calculate the total length of the structure and allocate it */ + WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + + NewName.Length; + WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize); + if (WaitPipeInfo == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Initialize the object attributes */ + TRACE("Opening: %wZ\n", &DevicePath); + InitializeObjectAttributes(&ObjectAttributes, + &DevicePath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the path */ + Status = NtOpenFile(&FileHandle, + FILE_READ_ATTRIBUTES | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + /* Fail; couldn't open */ + WARN("Status: %lx\n", Status); + BaseSetLastNTError(Status); + RtlFreeUnicodeString(&NamedPipeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo); + return FALSE; + } + + /* Check what timeout we got */ + if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT) + { + /* Don't use a timeout */ + WaitPipeInfo->TimeoutSpecified = FALSE; + } + else + { + /* Check if we should wait forever */ + if (nTimeOut == NMPWAIT_WAIT_FOREVER) + { + /* Set the max */ + WaitPipeInfo->Timeout.LowPart = 0; + WaitPipeInfo->Timeout.HighPart = 0x80000000; + } + else + { + /* Convert to NT format */ + WaitPipeInfo->Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut); + } + + /* In both cases, we do have a timeout */ + WaitPipeInfo->TimeoutSpecified = TRUE; + } + + /* Set the length and copy the name */ + WaitPipeInfo->NameLength = NewName.Length; + RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length); + + /* Get rid of the full name */ + RtlFreeUnicodeString(&NamedPipeName); + + /* Let NPFS know of our request */ + Status = NtFsControlFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_PIPE_WAIT, + WaitPipeInfo, + WaitPipeInfoSize, + NULL, + 0); + + /* Free our pipe info data and close the handle */ + RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo); + NtClose(FileHandle); + + /* Check the status */ + if (!NT_SUCCESS(Status)) + { + /* Failure to wait on the pipe */ + WARN("Status: %lx\n", Status); + BaseSetLastNTError (Status); + return FALSE; + } + + /* Success */ + return TRUE; +} +#else +/* + * @implemented + */ +BOOL +WINAPI +WaitNamedPipeW(LPCWSTR lpNamedPipeName, + DWORD nTimeOut) +{ + UNICODE_STRING NamedPipeName; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + FILE_PIPE_WAIT_FOR_BUFFER WaitPipe; + HANDLE FileHandle; + IO_STATUS_BLOCK Iosb; + + if (RtlDosPathNameToNtPathName_U(lpNamedPipeName, + &NamedPipeName, + NULL, + NULL) == FALSE) + { + return FALSE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NamedPipeName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenFile(&FileHandle, + FILE_READ_ATTRIBUTES | SYNCHRONIZE, + &ObjectAttributes, + &Iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + RtlFreeUnicodeString(&NamedPipeName); + return FALSE; + } + + /* Check what timeout we got */ + if (nTimeOut == NMPWAIT_WAIT_FOREVER) + { + /* Don't use a timeout */ + WaitPipe.TimeoutSpecified = FALSE; + } + else + { + /* Check if default */ + if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT) + { + /* Set it to 0 */ + WaitPipe.Timeout.LowPart = 0; + WaitPipe.Timeout.HighPart = 0; + } + else + { + /* Convert to NT format */ + WaitPipe.Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut); + } + + /* In both cases, we do have a timeout */ + WaitPipe.TimeoutSpecified = TRUE; + } + + Status = NtFsControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_WAIT, + &WaitPipe, + sizeof(WaitPipe), + NULL, + 0); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + RtlFreeUnicodeString(&NamedPipeName); + return FALSE; + } + + RtlFreeUnicodeString(&NamedPipeName); + return TRUE; +} +#endif + + +/* + * @implemented + */ +BOOL +WINAPI +ConnectNamedPipe(IN HANDLE hNamedPipe, + IN LPOVERLAPPED lpOverlapped) +{ + NTSTATUS Status; + + if (lpOverlapped != NULL) + { + PVOID ApcContext; + + lpOverlapped->Internal = STATUS_PENDING; + ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); + + Status = NtFsControlFile(hNamedPipe, + lpOverlapped->hEvent, + NULL, + ApcContext, + (PIO_STATUS_BLOCK)lpOverlapped, + FSCTL_PIPE_LISTEN, + NULL, + 0, + NULL, + 0); + + /* return FALSE in case of failure and pending operations! */ + if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) + { + BaseSetLastNTError(Status); + return FALSE; + } + } + else + { + IO_STATUS_BLOCK Iosb; + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_LISTEN, + NULL, + 0, + NULL, + 0); + + /* wait in case operation is pending */ + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (NT_SUCCESS(Status)) + { + Status = Iosb.Status; + } + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetNamedPipeHandleState(HANDLE hNamedPipe, + LPDWORD lpMode, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout) +{ + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + /* Check if the Mode is being changed */ + if (lpMode) + { + FILE_PIPE_INFORMATION Settings; + + /* Set the Completion Mode */ + Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ? + FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION; + + /* Set the Read Mode */ + Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ? + FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE; + + /* Send the changes to the Driver */ + Status = NtSetInformationFile(hNamedPipe, + &Iosb, + &Settings, + sizeof(FILE_PIPE_INFORMATION), + FilePipeInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + } + + /* Check if the Collection count or Timeout are being changed */ + if (lpMaxCollectionCount || lpCollectDataTimeout) + { + FILE_PIPE_REMOTE_INFORMATION RemoteSettings; + + /* Setting one without the other would delete it, so we read old one */ + if (!lpMaxCollectionCount || !lpCollectDataTimeout) + { + Status = NtQueryInformationFile(hNamedPipe, + &Iosb, + &RemoteSettings, + sizeof(FILE_PIPE_REMOTE_INFORMATION), + FilePipeRemoteInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + } + + /* Now set the new settings */ + RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ? + *lpMaxCollectionCount : + RemoteSettings.MaximumCollectionCount; + if (lpCollectDataTimeout) + { + /* Convert it to Quad */ + RemoteSettings.CollectDataTime.QuadPart = + -(LONGLONG)UInt32x32To64(10000, *lpCollectDataTimeout); + } + + /* Tell the driver to change them */ + Status = NtSetInformationFile(hNamedPipe, + &Iosb, + &RemoteSettings, + sizeof(FILE_PIPE_REMOTE_INFORMATION), + FilePipeRemoteInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +CallNamedPipeA(LPCSTR lpNamedPipeName, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + DWORD nTimeOut) +{ + PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString; + ANSI_STRING AnsiPipe; + + /* Initialize the string as ANSI_STRING and convert to Unicode */ + RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName); + RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE); + + /* Call the Unicode function */ + return CallNamedPipeW(PipeName->Buffer, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesRead, + nTimeOut); +} + + +/* + * @implemented + */ +BOOL +WINAPI +CallNamedPipeW(LPCWSTR lpNamedPipeName, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + DWORD nTimeOut) +{ + HANDLE hPipe; + BOOL bRetry = TRUE; + BOOL bError; + DWORD dwPipeMode; + + while (TRUE) + { + /* Try creating it */ + hPipe = CreateFileW(lpNamedPipeName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + /* Success, break out */ + if (hPipe != INVALID_HANDLE_VALUE) + break; + + /* Already tried twice, give up */ + if (bRetry == FALSE) + return FALSE; + + /* Wait on it */ + WaitNamedPipeW(lpNamedPipeName, nTimeOut); + + /* Get ready to try again */ + bRetry = FALSE; + } + + /* Set the pipe mode */ + dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; + bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL); + if (!bError) + { + /* Couldn't change state, fail */ + CloseHandle(hPipe); + return FALSE; + } + + /* Do the transact */ + bError = TransactNamedPipe(hPipe, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesRead, + NULL); + + /* Close the handle */ + CloseHandle(hPipe); + + return bError; +} + + +/* + * @implemented + */ +BOOL +WINAPI +DisconnectNamedPipe(HANDLE hNamedPipe) +{ + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + /* Send the FSCTL to the driver */ + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_DISCONNECT, + NULL, + 0, + NULL, + 0); + if (Status == STATUS_PENDING) + { + /* Wait on NPFS to finish and get updated status */ + Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL); + if (NT_SUCCESS(Status)) + Status = Iosb.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +GetNamedPipeHandleStateW(HANDLE hNamedPipe, + LPDWORD lpState, + LPDWORD lpCurInstances, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout, + LPWSTR lpUserName, + DWORD nMaxUserNameSize) +{ + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + if (lpState != NULL) + { + FILE_PIPE_INFORMATION PipeInfo; + + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &PipeInfo, + sizeof(FILE_PIPE_INFORMATION), + FilePipeInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT); + *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE); + } + + if(lpCurInstances != NULL) + { + FILE_PIPE_LOCAL_INFORMATION LocalInfo; + + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &LocalInfo, + sizeof(FILE_PIPE_LOCAL_INFORMATION), + FilePipeLocalInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES); + } + + if (lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL) + { + FILE_PIPE_REMOTE_INFORMATION RemoteInfo; + + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &RemoteInfo, + sizeof(FILE_PIPE_REMOTE_INFORMATION), + FilePipeRemoteInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if (lpMaxCollectionCount != NULL) + { + *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount; + } + + if(lpCollectDataTimeout != NULL) + { + /* FIXME */ + *lpCollectDataTimeout = 0; + } + } + + if (lpUserName != NULL) + { + /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and + retreive the user name with GetUserName(), revert the impersonation + and finally restore the thread token */ + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetNamedPipeHandleStateA(HANDLE hNamedPipe, + LPDWORD lpState, + LPDWORD lpCurInstances, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout, + LPSTR lpUserName, + DWORD nMaxUserNameSize) +{ + UNICODE_STRING UserNameW = { 0, 0, NULL }; + ANSI_STRING UserNameA; + BOOL Ret; + + if(lpUserName != NULL) + { + UserNameW.MaximumLength = (USHORT)nMaxUserNameSize * sizeof(WCHAR); + UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength); + if (UserNameW.Buffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + UserNameA.Buffer = lpUserName; + UserNameA.Length = 0; + UserNameA.MaximumLength = (USHORT)nMaxUserNameSize; + } + + Ret = GetNamedPipeHandleStateW(hNamedPipe, + lpState, + lpCurInstances, + lpMaxCollectionCount, + lpCollectDataTimeout, + UserNameW.Buffer, + nMaxUserNameSize); + if (Ret && lpUserName != NULL) + { + NTSTATUS Status; + + RtlInitUnicodeString(&UserNameW, UserNameW.Buffer); + Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + Ret = FALSE; + } + } + + if (UserNameW.Buffer != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer); + } + + return Ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetNamedPipeInfo(HANDLE hNamedPipe, + LPDWORD lpFlags, + LPDWORD lpOutBufferSize, + LPDWORD lpInBufferSize, + LPDWORD lpMaxInstances) +{ + FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation; + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &PipeLocalInformation, + sizeof(FILE_PIPE_LOCAL_INFORMATION), + FilePipeLocalInformation); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if (lpFlags != NULL) + { + *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END; + *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE; + } + + if (lpOutBufferSize != NULL) + *lpOutBufferSize = PipeLocalInformation.OutboundQuota; + + if (lpInBufferSize != NULL) + *lpInBufferSize = PipeLocalInformation.InboundQuota; + + if (lpMaxInstances != NULL) + { + if (PipeLocalInformation.MaximumInstances >= 255) + *lpMaxInstances = PIPE_UNLIMITED_INSTANCES; + else + *lpMaxInstances = PipeLocalInformation.MaximumInstances; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +PeekNamedPipe(HANDLE hNamedPipe, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage) +{ + PFILE_PIPE_PEEK_BUFFER Buffer; + IO_STATUS_BLOCK Iosb; + ULONG BufferSize; + ULONG BytesRead; + NTSTATUS Status; + + /* Calculate the buffer space that we'll need and allocate it */ + BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize); + if (Buffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Tell the driver to seek */ + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_PEEK, + NULL, + 0, + Buffer, + BufferSize); + if (Status == STATUS_PENDING) + { + /* Wait for npfs to be done, and update the status */ + Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL); + if (NT_SUCCESS(Status)) + Status = Iosb.Status; + } + + /* Overflow is success for us */ + if (Status == STATUS_BUFFER_OVERFLOW) + Status = STATUS_SUCCESS; + + /* If we failed */ + if (!NT_SUCCESS(Status)) + { + /* Free the buffer and return failure */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + BaseSetLastNTError(Status); + return FALSE; + } + + /* Check if caller requested bytes available */ + if (lpTotalBytesAvail) + *lpTotalBytesAvail = Buffer->ReadDataAvailable; + + /* Calculate the bytes returned, minus our structure overhead */ + BytesRead = (ULONG)(Iosb.Information - + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0])); + + /* Check if caller requested bytes read */ + if (lpBytesRead) + { + /* Return the bytes read */ + *lpBytesRead = BytesRead; + } + + /* Check if caller requested bytes left */ + if (lpBytesLeftThisMessage) + { + /* Calculate total minus what we returned and our structure overhead */ + *lpBytesLeftThisMessage = Buffer->MessageLength - BytesRead; + } + + /* Check if the caller wanted to see the actual data */ + if (lpBuffer) + { + /* Give him what he wants */ + RtlCopyMemory(lpBuffer, + Buffer->Data, + BytesRead); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +TransactNamedPipe(IN HANDLE hNamedPipe, + IN LPVOID lpInBuffer, + IN DWORD nInBufferSize, + OUT LPVOID lpOutBuffer, + IN DWORD nOutBufferSize, + OUT LPDWORD lpBytesRead OPTIONAL, + IN LPOVERLAPPED lpOverlapped OPTIONAL) +{ + NTSTATUS Status; + + if (lpBytesRead != NULL) + { + *lpBytesRead = 0; + } + + if (lpOverlapped != NULL) + { + PVOID ApcContext; + + ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); + lpOverlapped->Internal = STATUS_PENDING; + + Status = NtFsControlFile(hNamedPipe, + lpOverlapped->hEvent, + NULL, + ApcContext, + (PIO_STATUS_BLOCK)lpOverlapped, + FSCTL_PIPE_TRANSCEIVE, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if (lpBytesRead != NULL) + { + *lpBytesRead = lpOverlapped->InternalHigh; + } + } + else + { +#if 0 /* We don't implement FSCTL_PIPE_TRANSCEIVE yet */ + IO_STATUS_BLOCK Iosb; + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_TRANSCEIVE, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (NT_SUCCESS(Status)) + Status = Iosb.Status; + } + + if (NT_SUCCESS(Status)) + { + /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't + check that case either and crashes (only after the operation + completed) */ + *lpBytesRead = Iosb.Information; + } + else + { + BaseSetLastNTError(Status); + return FALSE; + } +#else /* Workaround while FSCTL_PIPE_TRANSCEIVE not available */ + DWORD nActualBytes; + + while (0 != nInBufferSize && + WriteFile(hNamedPipe, lpInBuffer, nInBufferSize, &nActualBytes, + NULL)) + { + lpInBuffer = (LPVOID)((char *) lpInBuffer + nActualBytes); + nInBufferSize -= nActualBytes; + } + + if (0 != nInBufferSize) + { + /* Must have dropped out of the while 'cause WriteFile failed */ + return FALSE; + } + + if (!ReadFile(hNamedPipe, lpOutBuffer, nOutBufferSize, &nActualBytes, + NULL)) + { + return FALSE; + } + + if (NULL != lpBytesRead) + { + *lpBytesRead = nActualBytes; + } +#endif + } + + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/pipe.c b/dll/win32/kernel32/client/file/pipe.c new file mode 100644 index 00000000000..c4539f70573 --- /dev/null +++ b/dll/win32/kernel32/client/file/pipe.c @@ -0,0 +1,127 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/create.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* GLOBALS ******************************************************************/ + +LONG ProcessPipeId = 0; + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +CreatePipe(PHANDLE hReadPipe, + PHANDLE hWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize) +{ + WCHAR Buffer[64]; + UNICODE_STRING PipeName; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK StatusBlock; + LARGE_INTEGER DefaultTimeout; + NTSTATUS Status; + HANDLE ReadPipeHandle; + HANDLE WritePipeHandle; + LONG PipeId; + ULONG Attributes; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + + /* Set the timeout to 120 seconds */ + DefaultTimeout.QuadPart = -1200000000; + + /* Use default buffer size if desired */ + if (!nSize) nSize = 0x1000; + + /* Increase the Pipe ID */ + PipeId = InterlockedIncrement(&ProcessPipeId); + + /* Create the pipe name */ + swprintf(Buffer, + L"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x", + NtCurrentTeb()->ClientId.UniqueProcess, + PipeId); + RtlInitUnicodeString(&PipeName, Buffer); + + /* Always use case insensitive */ + Attributes = OBJ_CASE_INSENSITIVE; + + /* Check if we got attributes */ + if (lpPipeAttributes) + { + /* Use the attributes' SD instead */ + SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor; + + /* Set OBJ_INHERIT if requested */ + if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT; + } + + /* Initialize the attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &PipeName, + Attributes, + NULL, + SecurityDescriptor); + + /* Create the named pipe */ + Status = NtCreateNamedPipeFile(&ReadPipeHandle, + GENERIC_READ |FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, + &ObjectAttributes, + &StatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + FILE_SYNCHRONOUS_IO_NONALERT, + FILE_PIPE_BYTE_STREAM_TYPE, + FILE_PIPE_BYTE_STREAM_MODE, + FILE_PIPE_QUEUE_OPERATION, + 1, + nSize, + nSize, + &DefaultTimeout); + if (!NT_SUCCESS(Status)) + { + /* Convert error and fail */ + WARN("Status: %lx\n", Status); + BaseSetLastNTError(Status); + return FALSE; + } + + /* Now try opening it for write access */ + Status = NtOpenFile(&WritePipeHandle, + FILE_GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &StatusBlock, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + { + /* Convert error and fail */ + WARN("Status: %lx\n", Status); + NtClose(ReadPipeHandle); + BaseSetLastNTError(Status); + return FALSE; + } + + /* Return both handles */ + *hReadPipe = ReadPipeHandle; + *hWritePipe = WritePipeHandle; + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/rw.c b/dll/win32/kernel32/client/file/rw.c new file mode 100644 index 00000000000..b5da581edf2 --- /dev/null +++ b/dll/win32/kernel32/client/file/rw.c @@ -0,0 +1,354 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/rw.c + * PURPOSE: Read/write functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +BOOL WINAPI +WriteFile(IN HANDLE hFile, + IN LPCVOID lpBuffer, + IN DWORD nNumberOfBytesToWrite OPTIONAL, + OUT LPDWORD lpNumberOfBytesWritten OPTIONAL, + IN LPOVERLAPPED lpOverlapped OPTIONAL) +{ + NTSTATUS Status; + + TRACE("WriteFile(hFile %x)\n", hFile); + + if (lpNumberOfBytesWritten != NULL) + { + *lpNumberOfBytesWritten = 0; + } + + hFile = TranslateStdHandle(hFile); + + if (IsConsoleHandle(hFile)) + { + return WriteConsoleA(hFile, + lpBuffer, + nNumberOfBytesToWrite, + lpNumberOfBytesWritten, + lpOverlapped); + } + + if (lpOverlapped != NULL) + { + LARGE_INTEGER Offset; + PVOID ApcContext; + + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + lpOverlapped->Internal = STATUS_PENDING; + ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); + + Status = NtWriteFile(hFile, + lpOverlapped->hEvent, + NULL, + ApcContext, + (PIO_STATUS_BLOCK)lpOverlapped, + (PVOID)lpBuffer, + nNumberOfBytesToWrite, + &Offset, + NULL); + + /* return FALSE in case of failure and pending operations! */ + if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) + { + BaseSetLastNTError(Status); + return FALSE; + } + + if (lpNumberOfBytesWritten != NULL) + { + *lpNumberOfBytesWritten = lpOverlapped->InternalHigh; + } + } + else + { + IO_STATUS_BLOCK Iosb; + + Status = NtWriteFile(hFile, + NULL, + NULL, + NULL, + &Iosb, + (PVOID)lpBuffer, + nNumberOfBytesToWrite, + NULL, + NULL); + + /* wait in case operation is pending */ + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hFile, + FALSE, + NULL); + if (NT_SUCCESS(Status)) + { + Status = Iosb.Status; + } + } + + if (NT_SUCCESS(Status)) + { + /* lpNumberOfBytesWritten must not be NULL here, in fact Win doesn't + check that case either and crashes (only after the operation + completed) */ + *lpNumberOfBytesWritten = Iosb.Information; + } + else + { + BaseSetLastNTError(Status); + return FALSE; + } + } + + TRACE("WriteFile() succeeded\n"); + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +ReadFile(IN HANDLE hFile, + IN LPVOID lpBuffer, + IN DWORD nNumberOfBytesToRead, + OUT LPDWORD lpNumberOfBytesRead OPTIONAL, + IN LPOVERLAPPED lpOverlapped OPTIONAL) +{ + NTSTATUS Status; + + TRACE("ReadFile(hFile %x)\n", hFile); + + if (lpNumberOfBytesRead != NULL) + { + *lpNumberOfBytesRead = 0; + } + + if (!nNumberOfBytesToRead) + { + return TRUE; + } + + hFile = TranslateStdHandle(hFile); + + if (IsConsoleHandle(hFile)) + { + if (ReadConsoleA(hFile, + lpBuffer, + nNumberOfBytesToRead, + lpNumberOfBytesRead, + NULL)) + { + DWORD dwMode; + GetConsoleMode(hFile, &dwMode); + if ((dwMode & ENABLE_PROCESSED_INPUT) && *(char *)lpBuffer == 0x1a) + { + /* EOF character entered; simulate end-of-file */ + *lpNumberOfBytesRead = 0; + } + return TRUE; + } + return FALSE; + } + + if (lpOverlapped != NULL) + { + LARGE_INTEGER Offset; + PVOID ApcContext; + + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + lpOverlapped->Internal = STATUS_PENDING; + ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); + + Status = NtReadFile(hFile, + lpOverlapped->hEvent, + NULL, + ApcContext, + (PIO_STATUS_BLOCK)lpOverlapped, + lpBuffer, + nNumberOfBytesToRead, + &Offset, + NULL); + + /* return FALSE in case of failure and pending operations! */ + if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) + { + if (Status == STATUS_END_OF_FILE && + lpNumberOfBytesRead != NULL) + { + *lpNumberOfBytesRead = 0; + } + + BaseSetLastNTError(Status); + return FALSE; + } + + if (lpNumberOfBytesRead != NULL) + { + *lpNumberOfBytesRead = lpOverlapped->InternalHigh; + } + } + else + { + IO_STATUS_BLOCK Iosb; + + Status = NtReadFile(hFile, + NULL, + NULL, + NULL, + &Iosb, + lpBuffer, + nNumberOfBytesToRead, + NULL, + NULL); + + /* wait in case operation is pending */ + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hFile, + FALSE, + NULL); + if (NT_SUCCESS(Status)) + { + Status = Iosb.Status; + } + } + + if (Status == STATUS_END_OF_FILE) + { + /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't + check that case either and crashes (only after the operation + completed) */ + *lpNumberOfBytesRead = 0; + return TRUE; + } + + if (NT_SUCCESS(Status)) + { + /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't + check that case either and crashes (only after the operation + completed) */ + *lpNumberOfBytesRead = Iosb.Information; + } + else + { + BaseSetLastNTError(Status); + return FALSE; + } + } + + TRACE("ReadFile() succeeded\n"); + return TRUE; +} + +VOID WINAPI +ApcRoutine(PVOID ApcContext, + struct _IO_STATUS_BLOCK* IoStatusBlock, + ULONG Reserved) +{ + DWORD dwErrorCode; + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine = + (LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext; + + dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); + lpCompletionRoutine(dwErrorCode, + IoStatusBlock->Information, + (LPOVERLAPPED)IoStatusBlock); +} + + +/* + * @implemented + */ +BOOL WINAPI +WriteFileEx(IN HANDLE hFile, + IN LPCVOID lpBuffer, + IN DWORD nNumberOfBytesToWrite OPTIONAL, + IN LPOVERLAPPED lpOverlapped, + IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + LARGE_INTEGER Offset; + NTSTATUS Status; + + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + lpOverlapped->Internal = STATUS_PENDING; + + Status = NtWriteFile(hFile, + NULL, + ApcRoutine, + lpCompletionRoutine, + (PIO_STATUS_BLOCK)lpOverlapped, + (PVOID)lpBuffer, + nNumberOfBytesToWrite, + &Offset, + NULL); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +ReadFileEx(IN HANDLE hFile, + IN LPVOID lpBuffer, + IN DWORD nNumberOfBytesToRead OPTIONAL, + IN LPOVERLAPPED lpOverlapped, + IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + LARGE_INTEGER Offset; + NTSTATUS Status; + + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + lpOverlapped->Internal = STATUS_PENDING; + + Status = NtReadFile(hFile, + NULL, + ApcRoutine, + lpCompletionRoutine, + (PIO_STATUS_BLOCK)lpOverlapped, + lpBuffer, + nNumberOfBytesToRead, + &Offset, + NULL); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/tape.c b/dll/win32/kernel32/client/file/tape.c new file mode 100644 index 00000000000..32e274fbab2 --- /dev/null +++ b/dll/win32/kernel32/client/file/tape.c @@ -0,0 +1,412 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/tape.c + * PURPOSE: Tape functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +DWORD WINAPI +CreateTapePartition (HANDLE hDevice, + DWORD dwPartitionMethod, + DWORD dwCount, + DWORD dwSize) +{ + TAPE_CREATE_PARTITION TapeCreatePartition; + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + TapeCreatePartition.Method = dwPartitionMethod; + TapeCreatePartition.Count = dwCount; + TapeCreatePartition.Size = dwSize; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_CREATE_PARTITION, + &TapeCreatePartition, + sizeof(TAPE_CREATE_PARTITION), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +EraseTape (HANDLE hDevice, + DWORD dwEraseType, + BOOL bImmediate) +{ + TAPE_ERASE TapeErase; + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + TapeErase.Type = dwEraseType; + TapeErase.Immediate = (BOOLEAN)bImmediate; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_ERASE, + &TapeErase, + sizeof(TAPE_ERASE), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetTapeParameters (HANDLE hDevice, + DWORD dwOperation, + LPDWORD lpdwSize, + LPVOID lpTapeInformation) +{ + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + if (dwOperation == GET_TAPE_MEDIA_INFORMATION) + { + if (*lpdwSize < sizeof(TAPE_GET_MEDIA_PARAMETERS)) + { + *lpdwSize = sizeof(TAPE_GET_MEDIA_PARAMETERS); + return ERROR_MORE_DATA; + } + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_GET_MEDIA_PARAMS, + NULL, + 0, + lpTapeInformation, + sizeof(TAPE_GET_MEDIA_PARAMETERS)); + } + else if (dwOperation == GET_TAPE_DRIVE_INFORMATION) + { + if (*lpdwSize < sizeof(TAPE_GET_DRIVE_PARAMETERS)) + { + *lpdwSize = sizeof(TAPE_GET_DRIVE_PARAMETERS); + return ERROR_MORE_DATA; + } + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_GET_DRIVE_PARAMS, + NULL, + 0, + lpTapeInformation, + sizeof(TAPE_GET_DRIVE_PARAMETERS)); + } + else + { + return ERROR_INVALID_FUNCTION; + } + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetTapePosition (HANDLE hDevice, + DWORD dwPositionType, + LPDWORD lpdwPartition, + LPDWORD lpdwOffsetLow, + LPDWORD lpdwOffsetHigh) +{ + TAPE_GET_POSITION TapeGetPosition; + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + TapeGetPosition.Type = dwPositionType; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_GET_POSITION, + &TapeGetPosition, + sizeof(TAPE_GET_POSITION), + &TapeGetPosition, + sizeof(TAPE_GET_POSITION)); + if (!NT_SUCCESS(Status)) + { + *lpdwPartition = 0; + *lpdwOffsetLow = 0; + *lpdwOffsetHigh = 0; + + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + *lpdwPartition = TapeGetPosition.Partition; + *lpdwOffsetLow = TapeGetPosition.Offset.u.LowPart; + *lpdwOffsetHigh = TapeGetPosition.Offset.u.HighPart; + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +GetTapeStatus (HANDLE hDevice) +{ + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_GET_STATUS, + NULL, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +PrepareTape (HANDLE hDevice, + DWORD dwOperation, + BOOL bImmediate) +{ + TAPE_PREPARE TapePrepare; + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + TapePrepare.Operation = dwOperation; + TapePrepare.Immediate = (BOOLEAN)bImmediate; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_PREPARE, + &TapePrepare, + sizeof(TAPE_PREPARE), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +SetTapeParameters (HANDLE hDevice, + DWORD dwOperation, + LPVOID lpTapeInformation) +{ + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + if (dwOperation == SET_TAPE_MEDIA_INFORMATION) + { + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_SET_MEDIA_PARAMS, + lpTapeInformation, + sizeof(TAPE_SET_MEDIA_PARAMETERS), + NULL, + 0); + } + else if (dwOperation == SET_TAPE_DRIVE_INFORMATION) + { + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_SET_DRIVE_PARAMS, + lpTapeInformation, + sizeof(TAPE_SET_DRIVE_PARAMETERS), + NULL, + 0); + } + else + { + return ERROR_INVALID_FUNCTION; + } + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +SetTapePosition (HANDLE hDevice, + DWORD dwPositionMethod, + DWORD dwPartition, + DWORD dwOffsetLow, + DWORD dwOffsetHigh, + BOOL bImmediate) +{ + TAPE_SET_POSITION TapeSetPosition; + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + TapeSetPosition.Method = dwPositionMethod; + TapeSetPosition.Partition = dwPartition; + TapeSetPosition.Offset.u.LowPart = dwOffsetLow; + TapeSetPosition.Offset.u.HighPart = dwOffsetHigh; + TapeSetPosition.Immediate = (BOOLEAN)bImmediate; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_SET_POSITION, + &TapeSetPosition, + sizeof(TAPE_SET_POSITION), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/* + * @implemented + */ +DWORD WINAPI +WriteTapemark (HANDLE hDevice, + DWORD dwTapemarkType, + DWORD dwTapemarkCount, + BOOL bImmediate) +{ + TAPE_WRITE_MARKS TapeWriteMarks; + IO_STATUS_BLOCK IoStatusBlock; + DWORD ErrorCode; + NTSTATUS Status; + + TapeWriteMarks.Type = dwTapemarkType; + TapeWriteMarks.Count = dwTapemarkCount; + TapeWriteMarks.Immediate = (BOOLEAN)bImmediate; + + Status = NtDeviceIoControlFile (hDevice, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_TAPE_WRITE_MARKS, + &TapeWriteMarks, + sizeof(TAPE_WRITE_MARKS), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/file/volume.c b/dll/win32/kernel32/client/file/volume.c new file mode 100644 index 00000000000..5323b1cef8e --- /dev/null +++ b/dll/win32/kernel32/client/file/volume.c @@ -0,0 +1,1558 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/volume.c + * PURPOSE: File volume functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Erik Bos, Alexandre Julliard : + * GetLogicalDriveStringsA, + * GetLogicalDriveStringsW, GetLogicalDrives + * UPDATE HISTORY: + * Created 01/11/98 + */ +//WINE copyright notice: +/* + * DOS drives handling functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(kernel32file); + +#define MAX_DOS_DRIVES 26 + + +static HANDLE +InternalOpenDirW(LPCWSTR DirName, + BOOLEAN Write) +{ + UNICODE_STRING NtPathU; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE hFile; + + if (!RtlDosPathNameToNtPathName_U(DirName, + &NtPathU, + NULL, + NULL)) + { + WARN("Invalid path\n"); + SetLastError(ERROR_BAD_PATHNAME); + return INVALID_HANDLE_VALUE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + errCode = NtCreateFile (&hFile, + Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError (errCode); + return INVALID_HANDLE_VALUE; + } + return hFile; +} + + +/* + * @implemented + */ +/* Synced to Wine-2008/12/28 */ +DWORD WINAPI +GetLogicalDriveStringsA(DWORD nBufferLength, + LPSTR lpBuffer) +{ + DWORD drive, count; + DWORD dwDriveMap; + LPSTR p; + + dwDriveMap = GetLogicalDrives(); + + for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) + { + if (dwDriveMap & (1< nBufferLength) return ((count * 4) + 1); + + p = lpBuffer; + + for (drive = 0; drive < MAX_DOS_DRIVES; drive++) + if (dwDriveMap & (1< nBufferLength) return ((count * 4) + 1); + + p = lpBuffer; + for (drive = 0; drive < MAX_DOS_DRIVES; drive++) + if (dwDriveMap & (1<QuadPart = + BytesPerCluster.QuadPart * FsInfo.FsFullSize.CallerAvailableAllocationUnits.QuadPart; + } + + if (lpTotalNumberOfBytes != NULL) + { + lpTotalNumberOfBytes->QuadPart = + BytesPerCluster.QuadPart * FsInfo.FsFullSize.TotalAllocationUnits.QuadPart; + } + + if (lpTotalNumberOfFreeBytes != NULL) + { + lpTotalNumberOfFreeBytes->QuadPart = + BytesPerCluster.QuadPart * FsInfo.FsFullSize.ActualAvailableAllocationUnits.QuadPart; + } + + return TRUE; + } + } + + Status = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + &FsInfo.FsSize, + sizeof(FsInfo.FsSize), + FileFsSizeInformation); + + /* Close the handle before returning data + to avoid a handle leak in case of a fault! */ + CloseHandle(hFile); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + BytesPerCluster.QuadPart = + FsInfo.FsSize.BytesPerSector * FsInfo.FsSize.SectorsPerAllocationUnit; + + if (lpFreeBytesAvailableToCaller) + { + lpFreeBytesAvailableToCaller->QuadPart = + BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart; + } + + if (lpTotalNumberOfBytes) + { + lpTotalNumberOfBytes->QuadPart = + BytesPerCluster.QuadPart * FsInfo.FsSize.TotalAllocationUnits.QuadPart; + } + + if (lpTotalNumberOfFreeBytes) + { + lpTotalNumberOfFreeBytes->QuadPart = + BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart; + } + + return TRUE; +} + + +/* + * @implemented + */ +UINT WINAPI +GetDriveTypeA(LPCSTR lpRootPathName) +{ + PWCHAR RootPathNameW; + + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return DRIVE_UNKNOWN; + + return GetDriveTypeW(RootPathNameW); +} + + +/* + * @implemented + */ +UINT WINAPI +GetDriveTypeW(LPCWSTR lpRootPathName) +{ + FILE_FS_DEVICE_INFORMATION FileFsDevice; + IO_STATUS_BLOCK IoStatusBlock; + + HANDLE hFile; + NTSTATUS errCode; + + hFile = InternalOpenDirW(lpRootPathName, FALSE); + if (hFile == INVALID_HANDLE_VALUE) + { + return DRIVE_NO_ROOT_DIR; /* According to WINE regression tests */ + } + + errCode = NtQueryVolumeInformationFile (hFile, + &IoStatusBlock, + &FileFsDevice, + sizeof(FILE_FS_DEVICE_INFORMATION), + FileFsDeviceInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + BaseSetLastNTError (errCode); + return 0; + } + CloseHandle(hFile); + + switch (FileFsDevice.DeviceType) + { + case FILE_DEVICE_CD_ROM: + case FILE_DEVICE_CD_ROM_FILE_SYSTEM: + return DRIVE_CDROM; + case FILE_DEVICE_VIRTUAL_DISK: + return DRIVE_RAMDISK; + case FILE_DEVICE_NETWORK_FILE_SYSTEM: + return DRIVE_REMOTE; + case FILE_DEVICE_DISK: + case FILE_DEVICE_DISK_FILE_SYSTEM: + if (FileFsDevice.Characteristics & FILE_REMOTE_DEVICE) + return DRIVE_REMOTE; + if (FileFsDevice.Characteristics & FILE_REMOVABLE_MEDIA) + return DRIVE_REMOVABLE; + return DRIVE_FIXED; + } + + ERR("Returning DRIVE_UNKNOWN for device type %d\n", FileFsDevice.DeviceType); + + return DRIVE_UNKNOWN; +} + + +/* + * @implemented + */ +BOOL WINAPI +GetVolumeInformationA( + LPCSTR lpRootPathName, + LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize + ) +{ + UNICODE_STRING FileSystemNameU; + UNICODE_STRING VolumeNameU = { 0, 0, NULL }; + ANSI_STRING VolumeName; + ANSI_STRING FileSystemName; + PWCHAR RootPathNameW; + BOOL Result; + + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return FALSE; + + if (lpVolumeNameBuffer) + { + VolumeNameU.MaximumLength = (USHORT)nVolumeNameSize * sizeof(WCHAR); + VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + VolumeNameU.MaximumLength); + if (VolumeNameU.Buffer == NULL) + { + goto FailNoMem; + } + } + + if (lpFileSystemNameBuffer) + { + FileSystemNameU.Length = 0; + FileSystemNameU.MaximumLength = (USHORT)nFileSystemNameSize * sizeof(WCHAR); + FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + FileSystemNameU.MaximumLength); + if (FileSystemNameU.Buffer == NULL) + { + if (VolumeNameU.Buffer != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + VolumeNameU.Buffer); + } + +FailNoMem: + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + } + + Result = GetVolumeInformationW (RootPathNameW, + lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL, + nVolumeNameSize, + lpVolumeSerialNumber, + lpMaximumComponentLength, + lpFileSystemFlags, + lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL, + nFileSystemNameSize); + + if (Result) + { + if (lpVolumeNameBuffer) + { + VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR); + VolumeName.Length = 0; + VolumeName.MaximumLength = (USHORT)nVolumeNameSize; + VolumeName.Buffer = lpVolumeNameBuffer; + } + + if (lpFileSystemNameBuffer) + { + FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR); + FileSystemName.Length = 0; + FileSystemName.MaximumLength = (USHORT)nFileSystemNameSize; + FileSystemName.Buffer = lpFileSystemNameBuffer; + } + + /* convert unicode strings to ansi (or oem) */ + if (bIsFileApiAnsi) + { + if (lpVolumeNameBuffer) + { + RtlUnicodeStringToAnsiString (&VolumeName, + &VolumeNameU, + FALSE); + } + if (lpFileSystemNameBuffer) + { + RtlUnicodeStringToAnsiString (&FileSystemName, + &FileSystemNameU, + FALSE); + } + } + else + { + if (lpVolumeNameBuffer) + { + RtlUnicodeStringToOemString (&VolumeName, + &VolumeNameU, + FALSE); + } + if (lpFileSystemNameBuffer) + { + RtlUnicodeStringToOemString (&FileSystemName, + &FileSystemNameU, + FALSE); + } + } + } + + if (lpVolumeNameBuffer) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VolumeNameU.Buffer); + } + if (lpFileSystemNameBuffer) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileSystemNameU.Buffer); + } + + return Result; +} + +#define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION)) + +#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) + +/* + * @implemented + */ +BOOL WINAPI +GetVolumeInformationW( + LPCWSTR lpRootPathName, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize + ) +{ + PFILE_FS_VOLUME_INFORMATION FileFsVolume; + PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute; + IO_STATUS_BLOCK IoStatusBlock; + WCHAR RootPathName[MAX_PATH]; + UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)]; + + HANDLE hFile; + NTSTATUS errCode; + + FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer; + FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer; + + TRACE("FileFsVolume %p\n", FileFsVolume); + TRACE("FileFsAttribute %p\n", FileFsAttribute); + + if (!lpRootPathName || !wcscmp(lpRootPathName, L"")) + { + GetCurrentDirectoryW (MAX_PATH, RootPathName); + } + else + { + wcsncpy (RootPathName, lpRootPathName, 3); + } + RootPathName[3] = 0; + + hFile = InternalOpenDirW(RootPathName, FALSE); + if (hFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + TRACE("hFile: %x\n", hFile); + errCode = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + FileFsVolume, + FS_VOLUME_BUFFER_SIZE, + FileFsVolumeInformation); + if ( !NT_SUCCESS(errCode) ) + { + WARN("Status: %x\n", errCode); + CloseHandle(hFile); + BaseSetLastNTError (errCode); + return FALSE; + } + + if (lpVolumeSerialNumber) + *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber; + + if (lpVolumeNameBuffer) + { + if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR)) + { + memcpy(lpVolumeNameBuffer, + FileFsVolume->VolumeLabel, + FileFsVolume->VolumeLabelLength); + lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0; + } + else + { + CloseHandle(hFile); + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + } + + errCode = NtQueryVolumeInformationFile (hFile, + &IoStatusBlock, + FileFsAttribute, + FS_ATTRIBUTE_BUFFER_SIZE, + FileFsAttributeInformation); + CloseHandle(hFile); + if (!NT_SUCCESS(errCode)) + { + WARN("Status: %x\n", errCode); + BaseSetLastNTError (errCode); + return FALSE; + } + + if (lpFileSystemFlags) + *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes; + if (lpMaximumComponentLength) + *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength; + if (lpFileSystemNameBuffer) + { + if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR)) + { + memcpy(lpFileSystemNameBuffer, + FileFsAttribute->FileSystemName, + FileFsAttribute->FileSystemNameLength); + lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0; + } + else + { + SetLastError(ERROR_MORE_DATA); + return FALSE; + } + } + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetVolumeLabelA ( + LPCSTR lpRootPathName, + LPCSTR lpVolumeName /* NULL if deleting label */ + ) +{ + PWCHAR RootPathNameW; + PWCHAR VolumeNameW = NULL; + BOOL Result; + + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return FALSE; + + if (lpVolumeName) + { + if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE))) + return FALSE; + } + + Result = SetVolumeLabelW (RootPathNameW, + VolumeNameW); + + if (VolumeNameW) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VolumeNameW ); + } + + return Result; +} + + +/* + * @implemented + */ +BOOL WINAPI +SetVolumeLabelW( + LPCWSTR lpRootPathName, + LPCWSTR lpVolumeName /* NULL if deleting label */ + ) +{ + PFILE_FS_LABEL_INFORMATION LabelInfo; + IO_STATUS_BLOCK IoStatusBlock; + ULONG LabelLength; + HANDLE hFile; + NTSTATUS Status; + + LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR); + LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(FILE_FS_LABEL_INFORMATION) + + LabelLength); + if (LabelInfo == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + LabelInfo->VolumeLabelLength = LabelLength; + memcpy(LabelInfo->VolumeLabel, + lpVolumeName, + LabelLength); + + hFile = InternalOpenDirW(lpRootPathName, TRUE); + if (INVALID_HANDLE_VALUE == hFile) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + LabelInfo); + return FALSE; + } + + Status = NtSetVolumeInformationFile(hFile, + &IoStatusBlock, + LabelInfo, + sizeof(FILE_FS_LABEL_INFORMATION) + + LabelLength, + FileFsLabelInformation); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + LabelInfo); + + if (!NT_SUCCESS(Status)) + { + WARN("Status: %x\n", Status); + CloseHandle(hFile); + BaseSetLastNTError(Status); + return FALSE; + } + + CloseHandle(hFile); + return TRUE; +} + +/** + * @name GetVolumeNameForVolumeMountPointW + * + * Return an unique volume name for a drive root or mount point. + * + * @param VolumeMountPoint + * Pointer to string that contains either root drive name or + * mount point name. + * @param VolumeName + * Pointer to buffer that is filled with resulting unique + * volume name on success. + * @param VolumeNameLength + * Size of VolumeName buffer in TCHARs. + * + * @return + * TRUE when the function succeeds and the VolumeName buffer is filled, + * FALSE otherwise. + */ + +BOOL WINAPI +GetVolumeNameForVolumeMountPointW( + IN LPCWSTR VolumeMountPoint, + OUT LPWSTR VolumeName, + IN DWORD VolumeNameLength) +{ + UNICODE_STRING NtFileName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE FileHandle; + IO_STATUS_BLOCK Iosb; + ULONG BufferLength; + PMOUNTDEV_NAME MountDevName; + PMOUNTMGR_MOUNT_POINT MountPoint; + ULONG MountPointSize; + PMOUNTMGR_MOUNT_POINTS MountPoints; + ULONG Index; + PUCHAR SymbolicLinkName; + BOOL Result; + NTSTATUS Status; + + if (!VolumeMountPoint || !VolumeMountPoint[0]) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + /* + * First step is to convert the passed volume mount point name to + * an NT acceptable name. + */ + + if (!RtlDosPathNameToNtPathName_U(VolumeMountPoint, &NtFileName, NULL, NULL)) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return FALSE; + } + + if (NtFileName.Length > sizeof(WCHAR) && + NtFileName.Buffer[(NtFileName.Length / sizeof(WCHAR)) - 1] == '\\') + { + NtFileName.Length -= sizeof(WCHAR); + } + + /* + * Query mount point device name which we will later use for determining + * the volume name. + */ + + InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL); + Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, + &ObjectAttributes, &Iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT); + RtlFreeUnicodeString(&NtFileName); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR); + do + { + MountDevName = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength); + if (MountDevName == NULL) + { + NtClose(FileHandle); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, + IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, + NULL, 0, MountDevName, BufferLength); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, MountDevName); + if (Status == STATUS_BUFFER_OVERFLOW) + { + BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength; + continue; + } + else + { + NtClose(FileHandle); + BaseSetLastNTError(Status); + return FALSE; + } + } + } + while (!NT_SUCCESS(Status)); + + NtClose(FileHandle); + + /* + * Get the mount point information from mount manager. + */ + + MountPointSize = MountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT); + MountPoint = RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize); + if (MountPoint == NULL) + { + RtlFreeHeap(GetProcessHeap(), 0, MountDevName); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + RtlZeroMemory(MountPoint, sizeof(MOUNTMGR_MOUNT_POINT)); + MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT); + MountPoint->DeviceNameLength = MountDevName->NameLength; + RtlCopyMemory(MountPoint + 1, MountDevName->Name, MountDevName->NameLength); + RtlFreeHeap(RtlGetProcessHeap(), 0, MountDevName); + + RtlInitUnicodeString(&NtFileName, L"\\??\\MountPointManager"); + InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL); + Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, + &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); + return FALSE; + } + + BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS); + do + { + MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength); + if (MountPoints == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); + NtClose(FileHandle); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, + IOCTL_MOUNTMGR_QUERY_POINTS, + MountPoint, MountPointSize, + MountPoints, BufferLength); + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_BUFFER_OVERFLOW) + { + BufferLength = MountPoints->Size; + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); + continue; + } + else if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); + NtClose(FileHandle); + BaseSetLastNTError(Status); + return FALSE; + } + } + } + while (!NT_SUCCESS(Status)); + + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint); + NtClose(FileHandle); + + /* + * Now we've gathered info about all mount points mapped to our device, so + * select the correct one and copy it into the output buffer. + */ + + for (Index = 0; Index < MountPoints->NumberOfMountPoints; Index++) + { + MountPoint = MountPoints->MountPoints + Index; + SymbolicLinkName = (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset; + + /* + * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" + * (with the last slash being optional) style symbolic links. + */ + + if (MountPoint->SymbolicLinkNameLength == 48 * sizeof(WCHAR) || + (MountPoint->SymbolicLinkNameLength == 49 * sizeof(WCHAR) && + SymbolicLinkName[48] == L'\\')) + { + if (RtlCompareMemory(SymbolicLinkName, L"\\??\\Volume{", + 11 * sizeof(WCHAR)) == 11 * sizeof(WCHAR) && + SymbolicLinkName[19] == L'-' && SymbolicLinkName[24] == L'-' && + SymbolicLinkName[29] == L'-' && SymbolicLinkName[34] == L'-' && + SymbolicLinkName[47] == L'}') + { + if (VolumeNameLength >= MountPoint->SymbolicLinkNameLength / sizeof(WCHAR)) + { + RtlCopyMemory(VolumeName, + (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset, + MountPoint->SymbolicLinkNameLength); + VolumeName[1] = L'\\'; + Result = TRUE; + } + else + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + Result = FALSE; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); + + return Result; + } + } + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints); + SetLastError(ERROR_INVALID_PARAMETER); + + return FALSE; +} + +/* + * @implemented (Wine 13 sep 2008) + */ +BOOL +WINAPI +GetVolumeNameForVolumeMountPointA( + LPCSTR lpszVolumeMountPoint, + LPSTR lpszVolumeName, + DWORD cchBufferLength + ) +{ + BOOL ret; + WCHAR volumeW[50], *pathW = NULL; + DWORD len = min( sizeof(volumeW) / sizeof(WCHAR), cchBufferLength ); + + TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint), lpszVolumeName, cchBufferLength); + + if (!lpszVolumeMountPoint || !(pathW = FilenameA2W( lpszVolumeMountPoint, TRUE ))) + return FALSE; + + if ((ret = GetVolumeNameForVolumeMountPointW( pathW, volumeW, len ))) + FilenameW2A_N( lpszVolumeName, len, volumeW, -1 ); + + RtlFreeHeap( RtlGetProcessHeap(), 0, pathW ); + return ret; +} + +/* + * @implemented (Wine 13 sep 2008) + */ +HANDLE +WINAPI +FindFirstVolumeW( + LPWSTR volume, + DWORD len + ) +{ + DWORD size = 1024; + HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE ); + if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; + + for (;;) + { + MOUNTMGR_MOUNT_POINT input; + MOUNTMGR_MOUNT_POINTS *output; + + if (!(output = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + break; + } + memset( &input, 0, sizeof(input) ); + + if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, &input, sizeof(input), + output, size, NULL, NULL )) + { + if (GetLastError() != ERROR_MORE_DATA) break; + size = output->Size; + RtlFreeHeap( RtlGetProcessHeap(), 0, output ); + continue; + } + CloseHandle( mgr ); + /* abuse the Size field to store the current index */ + output->Size = 0; + if (!FindNextVolumeW( output, volume, len )) + { + RtlFreeHeap( RtlGetProcessHeap(), 0, output ); + return INVALID_HANDLE_VALUE; + } + return (HANDLE)output; + } + CloseHandle( mgr ); + return INVALID_HANDLE_VALUE; +} + +/* + * @implemented (Wine 13 sep 2008) + */ +HANDLE +WINAPI +FindFirstVolumeA( + LPSTR volume, + DWORD len + ) +{ + WCHAR *buffer = NULL; + HANDLE handle; + + buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, len * sizeof(WCHAR) ); + + if (!buffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return INVALID_HANDLE_VALUE; + } + + handle = FindFirstVolumeW( buffer, len ); + + if (handle != INVALID_HANDLE_VALUE) + { + if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) + { + FindVolumeClose( handle ); + handle = INVALID_HANDLE_VALUE; + } + } + RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); + return handle; +} + +/* + * @implemented (Wine 13 sep 2008) + */ +BOOL +WINAPI +FindVolumeClose( + HANDLE hFindVolume + ) +{ + return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume); +} + +/* + * @implemented + */ +BOOL +WINAPI +GetVolumePathNameA(LPCSTR lpszFileName, + LPSTR lpszVolumePathName, + DWORD cchBufferLength) +{ + PWCHAR FileNameW = NULL; + WCHAR VolumePathName[MAX_PATH]; + BOOL Result; + + if (lpszFileName) + { + if (!(FileNameW = FilenameA2W(lpszFileName, FALSE))) + return FALSE; + } + + Result = GetVolumePathNameW(FileNameW, VolumePathName, cchBufferLength); + + if (Result) + FilenameW2A_N(lpszVolumePathName, MAX_PATH, VolumePathName, -1); + + return Result; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetVolumePathNameW(LPCWSTR lpszFileName, + LPWSTR lpszVolumePathName, + DWORD cchBufferLength) +{ + DWORD PathLength; + UNICODE_STRING UnicodeFilePath; + LPWSTR FilePart; + PWSTR FullFilePath, FilePathName; + ULONG PathSize; + WCHAR VolumeName[MAX_PATH]; + DWORD ErrorCode; + BOOL Result = FALSE; + + if (!(PathLength = GetFullPathNameW(lpszFileName, 0, NULL, NULL))) + { + return Result; + } + else + { + PathLength = PathLength + 10; + PathSize = PathLength * sizeof(WCHAR); + + if (!(FullFilePath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize))) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return Result; + } + + if (!GetFullPathNameW(lpszFileName, PathLength, FullFilePath, &FilePart)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath); + return Result; + } + + RtlInitUnicodeString(&UnicodeFilePath, FullFilePath); + + if (UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] != '\\') + { + UnicodeFilePath.Length += sizeof(WCHAR); + UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] = '\\'; + UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; + } + + if (!(FilePathName = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize))) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return Result; + } + + while (!GetVolumeNameForVolumeMountPointW(UnicodeFilePath.Buffer, + VolumeName, + MAX_PATH)) + { + if (((UnicodeFilePath.Length == 4) && (UnicodeFilePath.Buffer[0] == '\\') && + (UnicodeFilePath.Buffer[1] == '\\')) || ((UnicodeFilePath.Length == 6) && + (UnicodeFilePath.Buffer[1] == ':'))) + { + break; + } + + UnicodeFilePath.Length -= sizeof(WCHAR); + UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; + + memcpy(FilePathName, UnicodeFilePath.Buffer, UnicodeFilePath.Length); + FilePathName[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; + + if (!GetFullPathNameW(FilePathName, PathLength, FullFilePath, &FilePart)) + { + goto Cleanup2; + } + + if (!FilePart) + { + RtlInitUnicodeString(&UnicodeFilePath, FullFilePath); + UnicodeFilePath.Length += sizeof(WCHAR); + UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] = '\\'; + UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; + break; + } + + FilePart[0] = '\0'; + RtlInitUnicodeString(&UnicodeFilePath, FullFilePath); + } + } + + if (UnicodeFilePath.Length > (cchBufferLength * sizeof(WCHAR)) - sizeof(WCHAR)) + { + ErrorCode = ERROR_FILENAME_EXCED_RANGE; + goto Cleanup1; + } + + memcpy(lpszVolumePathName, UnicodeFilePath.Buffer, UnicodeFilePath.Length); + lpszVolumePathName[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0'; + + Result = TRUE; + goto Cleanup2; + +Cleanup1: + SetLastError(ErrorCode); +Cleanup2: + RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath); + RtlFreeHeap(RtlGetProcessHeap(), 0, FilePathName); + return Result; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +SetVolumeMountPointW( + LPCWSTR lpszVolumeMountPoint, + LPCWSTR lpszVolumeName + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +DeleteVolumeMountPointA( + LPCSTR lpszVolumeMountPoint + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +HANDLE +WINAPI +FindFirstVolumeMountPointA( + LPCSTR lpszRootPathName, + LPSTR lpszVolumeMountPoint, + DWORD cchBufferLength + ) +{ + STUB; + return 0; +} + +/* + * @implemented + */ +BOOL +WINAPI +FindNextVolumeA(HANDLE handle, + LPSTR volume, + DWORD len) +{ + WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR)); + BOOL ret; + + if (!buffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + if ((ret = FindNextVolumeW( handle, buffer, len ))) + { + if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE; + } + + HeapFree( GetProcessHeap(), 0, buffer ); + return ret; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +FindNextVolumeMountPointA( + HANDLE hFindVolumeMountPoint, + LPSTR lpszVolumeMountPoint, + DWORD cchBufferLength + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetVolumePathNamesForVolumeNameA( + LPCSTR lpszVolumeName, + LPSTR lpszVolumePathNames, + DWORD cchBufferLength, + PDWORD lpcchReturnLength + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetVolumeMountPointA( + LPCSTR lpszVolumeMountPoint, + LPCSTR lpszVolumeName + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +FindVolumeMountPointClose( + HANDLE hFindVolumeMountPoint + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +DeleteVolumeMountPointW( + LPCWSTR lpszVolumeMountPoint + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +HANDLE +WINAPI +FindFirstVolumeMountPointW( + LPCWSTR lpszRootPathName, + LPWSTR lpszVolumeMountPoint, + DWORD cchBufferLength + ) +{ + STUB; + return 0; +} + +/* + * @implemented + */ +BOOL +WINAPI +FindNextVolumeW( + HANDLE handle, + LPWSTR volume, + DWORD len + ) +{ + MOUNTMGR_MOUNT_POINTS *data = handle; + + while (data->Size < data->NumberOfMountPoints) + { + static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',}; + WCHAR *link = (WCHAR *)((char *)data + data->MountPoints[data->Size].SymbolicLinkNameOffset); + DWORD size = data->MountPoints[data->Size].SymbolicLinkNameLength; + data->Size++; + /* skip non-volumes */ + if (size < sizeof(volumeW) || memcmp( link, volumeW, sizeof(volumeW) )) continue; + if (size + sizeof(WCHAR) >= len * sizeof(WCHAR)) + { + SetLastError( ERROR_FILENAME_EXCED_RANGE ); + return FALSE; + } + memcpy( volume, link, size ); + volume[1] = '\\'; /* map \??\ to \\?\ */ + volume[size / sizeof(WCHAR)] = '\\'; /* Windows appends a backslash */ + volume[size / sizeof(WCHAR) + 1] = 0; + DPRINT( "returning entry %u %s\n", data->Size - 1, volume ); + return TRUE; + } + SetLastError( ERROR_NO_MORE_FILES ); + return FALSE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +FindNextVolumeMountPointW( + HANDLE hFindVolumeMountPoint, + LPWSTR lpszVolumeMountPoint, + DWORD cchBufferLength + ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetVolumePathNamesForVolumeNameW( + LPCWSTR lpszVolumeName, + LPWSTR lpszVolumePathNames, + DWORD cchBufferLength, + PDWORD lpcchReturnLength + ) +{ + STUB; + return 0; +} + + +/* EOF */ diff --git a/dll/win32/kernel32/client/handle.c b/dll/win32/kernel32/client/handle.c new file mode 100644 index 00000000000..3f5eef262f7 --- /dev/null +++ b/dll/win32/kernel32/client/handle.c @@ -0,0 +1,260 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/handle.c + * PURPOSE: Object functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +HANDLE WINAPI +DuplicateConsoleHandle (HANDLE hConsole, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions); + +/* FUNCTIONS *****************************************************************/ + +HANDLE FASTCALL +TranslateStdHandle(HANDLE hHandle) +{ + PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters; + + switch ((ULONG)hHandle) + { + case STD_INPUT_HANDLE: return Ppb->StandardInput; + case STD_OUTPUT_HANDLE: return Ppb->StandardOutput; + case STD_ERROR_HANDLE: return Ppb->StandardError; + } + + return hHandle; +} + +/* + * @implemented + */ +BOOL WINAPI +GetHandleInformation (HANDLE hObject, + LPDWORD lpdwFlags) +{ + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; + ULONG BytesWritten; + NTSTATUS Status; + DWORD Flags; + + hObject = TranslateStdHandle(hObject); + + Status = NtQueryObject (hObject, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), + &BytesWritten); + if (NT_SUCCESS(Status)) + { + Flags = 0; + if (HandleInfo.Inherit) + Flags |= HANDLE_FLAG_INHERIT; + if (HandleInfo.ProtectFromClose) + Flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; + + *lpdwFlags = Flags; + + return TRUE; + } + else + { + BaseSetLastNTError (Status); + return FALSE; + } +} + + +/* + * @implemented + */ +BOOL WINAPI +SetHandleInformation (HANDLE hObject, + DWORD dwMask, + DWORD dwFlags) +{ + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; + ULONG BytesWritten; + NTSTATUS Status; + + hObject = TranslateStdHandle(hObject); + + Status = NtQueryObject (hObject, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), + &BytesWritten); + if (NT_SUCCESS(Status)) + { + if (dwMask & HANDLE_FLAG_INHERIT) + HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; + if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) + HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; + + Status = NtSetInformationObject (hObject, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION)); + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; + } + else + { + BaseSetLastNTError (Status); + return FALSE; + } +} + + +/* + * @implemented + */ +BOOL WINAPI CloseHandle(HANDLE hObject) +/* + * FUNCTION: Closes an open object handle + * PARAMETERS: + * hObject = Identifies an open object handle + * RETURNS: If the function succeeds, the return value is nonzero + * If the function fails, the return value is zero + */ +{ + NTSTATUS Status; + + hObject = TranslateStdHandle(hObject); + + if (IsConsoleHandle(hObject)) + { + return(CloseConsoleHandle(hObject)); + } + + Status = NtClose(hObject); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI DuplicateHandle(HANDLE hSourceProcessHandle, + HANDLE hSourceHandle, + HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions) +{ + DWORD SourceProcessId, TargetProcessId; + NTSTATUS Status; + + hSourceHandle = TranslateStdHandle(hSourceHandle); + + if (IsConsoleHandle(hSourceHandle)) + { + SourceProcessId = GetProcessId(hSourceProcessHandle); + TargetProcessId = GetProcessId(hTargetProcessHandle); + if (!SourceProcessId || !TargetProcessId || + SourceProcessId != TargetProcessId || + SourceProcessId != GetCurrentProcessId()) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + *lpTargetHandle = DuplicateConsoleHandle(hSourceHandle, dwDesiredAccess, bInheritHandle, dwOptions); + return *lpTargetHandle != INVALID_HANDLE_VALUE; + } + + Status = NtDuplicateObject(hSourceProcessHandle, + hSourceHandle, + hTargetProcessHandle, + lpTargetHandle, + dwDesiredAccess, + bInheritHandle ? OBJ_INHERIT : 0, + dwOptions); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError (Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +UINT +WINAPI +SetHandleCount(UINT nCount) +{ + return nCount; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetHandleContext(IN HANDLE Handle) +{ + /* This is Windows behavior, not a ReactOS Stub */ + DbgPrintEx(0, 0, "Unsupported API - kernel32!GetHandleContext() called\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateSocketHandle(VOID) +{ + /* This is Windows behavior, not a ReactOS Stub */ + DbgPrintEx(0, 0, "Unsupported API - kernel32!CreateSocketHandle() called\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + +} + +/* + * @implemented + */ +BOOL +WINAPI +SetHandleContext(IN HANDLE Handle, + IN DWORD Context) +{ + /* This is Windows behavior, not a ReactOS Stub */ + DbgPrintEx(0, 0, "Unsupported API - kernel32!SetHandleContext() called\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/mem/global.c b/dll/win32/kernel32/client/heapmem.c similarity index 57% rename from dll/win32/kernel32/mem/global.c rename to dll/win32/kernel32/client/heapmem.c index a0449e36fca..808e31b7fbf 100644 --- a/dll/win32/kernel32/mem/global.c +++ b/dll/win32/kernel32/client/heapmem.c @@ -1,8 +1,8 @@ /* * PROJECT: ReactOS Win32 Base API * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/mem/global.c - * PURPOSE: Global Memory APIs (sits on top of Heap*) + * FILE: dll/win32/kernel32/mem/heap.c + * PURPOSE: Heap Memory APIs (wrappers for RtlHeap*) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ @@ -15,11 +15,331 @@ /* TYPES *********************************************************************/ -extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo; RTL_HANDLE_TABLE BaseHeapHandleTable; /* FUNCTIONS ***************************************************************/ +/* + * @implemented + */ +HANDLE +WINAPI +HeapCreate(DWORD flOptions, + DWORD dwInitialSize, + DWORD dwMaximumSize) +{ + HANDLE hRet; + ULONG Flags; + + /* Remove non-Win32 flags and tag this allocation */ + Flags = (flOptions & (HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE)) | + HEAP_CLASS_1; + + /* Check if heap is growable and ensure max size is correct */ + if (dwMaximumSize == 0) + Flags |= HEAP_GROWABLE; + else if (dwMaximumSize < BaseStaticServerData->SysInfo.PageSize && + dwInitialSize > dwMaximumSize) + { + /* Max size is non-zero but less than page size which can't be correct. + Fix it up by bumping it to the initial size whatever it is. */ + dwMaximumSize = dwInitialSize; + } + + /* Call RTL Heap */ + hRet = RtlCreateHeap(Flags, + NULL, + dwMaximumSize, + dwInitialSize, + NULL, + NULL); + + /* Set the last error if we failed, and return the pointer */ + if (!hRet) SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return hRet; +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapDestroy(HANDLE hHeap) +{ + /* Return TRUE if the heap was destroyed */ + if (!RtlDestroyHeap(hHeap)) return TRUE; + + /* Otherwise, we got the handle back, so fail */ + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +GetProcessHeap(VOID) +{ + /* Call the RTL API */ + return RtlGetProcessHeap(); +} + +/* + * @implemented + */ +DWORD +WINAPI +GetProcessHeaps(DWORD NumberOfHeaps, + PHANDLE ProcessHeaps) +{ + /* Call the RTL API */ + return RtlGetProcessHeaps(NumberOfHeaps, ProcessHeaps); +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapLock(HANDLE hHeap) +{ + /* Call the RTL API */ + return RtlLockHeap(hHeap); +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapUnlock(HANDLE hHeap) +{ + /* Call the RTL API */ + return RtlUnlockHeap(hHeap); +} + +/* + * @implemented + */ +SIZE_T +WINAPI +HeapCompact(HANDLE hHeap, DWORD dwFlags) +{ + /* Call the RTL API */ + return RtlCompactHeap(hHeap, dwFlags); +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapValidate(HANDLE hHeap, + DWORD dwFlags, + LPCVOID lpMem) +{ + /* Call the RTL API */ + return RtlValidateHeap(hHeap, dwFlags, (PVOID)lpMem); +} + +/* + * @implemented + */ +DWORD +WINAPI +HeapCreateTagsW(HANDLE hHeap, + DWORD dwFlags, + PWSTR lpTagName, + PWSTR lpTagSubName) +{ + /* Call the RTL API */ + return RtlCreateTagHeap(hHeap, + dwFlags, + lpTagName, + lpTagSubName); +} + +/* + * @implemented + */ +DWORD +WINAPI +HeapExtend(HANDLE hHeap, + DWORD dwFlags, + PVOID BaseAddress, + DWORD dwBytes) +{ + NTSTATUS Status; + + /* Call the RTL API. Gone in Vista, so commented out. */ + Status = STATUS_NOT_IMPLEMENTED; //RtlExtendHeap(hHeap, dwFlags, BaseAddress, dwBytes); + if (!NT_SUCCESS(Status)) + { + /* We failed */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Return success */ + return TRUE; +} + +/* + * @implemented + */ +PWSTR +WINAPI +HeapQueryTagW(HANDLE hHeap, + DWORD dwFlags, + WORD wTagIndex, + BOOL bResetCounters, + PVOID lpTagInfo) +{ + /* Call the RTL API */ + return RtlQueryTagHeap(hHeap, + dwFlags, + wTagIndex, + (BOOLEAN)bResetCounters, + lpTagInfo); +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapSummary(HANDLE hHeap, + DWORD dwFlags, + PVOID Summary) +{ + NTSTATUS Status; + RTL_HEAP_USAGE Usage; + + /* Fill in the length information */ + Usage.Length = sizeof(Usage); + + /* Call RTL. Gone in Vista, so commented out */ + Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage); + if (!NT_SUCCESS(Status)) + { + /* We failed */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* FIXME: Summary == Usage?! */ + RtlCopyMemory(Summary, &Usage, sizeof(Usage)); + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapUsage(HANDLE hHeap, + DWORD dwFlags, + DWORD Unknown, + DWORD Unknown2, + IN PVOID Usage) +{ + NTSTATUS Status; + + /* Call RTL. Gone in Vista, so commented out */ + Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage); + if (!NT_SUCCESS(Status)) + { + /* We failed */ + BaseSetLastNTError(Status); + return FALSE; + } + else if (Status == STATUS_MORE_ENTRIES) + { + /* There are still more entries to parse */ + return TRUE; + } + + /* Otherwise, we're completely done, so we return FALSE, but NO_ERROR */ + SetLastError(NO_ERROR); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapWalk(HANDLE hHeap, + LPPROCESS_HEAP_ENTRY lpEntry) +{ + NTSTATUS Status; + + Status = RtlWalkHeap(hHeap, lpEntry); + + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapQueryInformation(HANDLE HeapHandle, + HEAP_INFORMATION_CLASS HeapInformationClass, + PVOID HeapInformation OPTIONAL, + SIZE_T HeapInformationLength OPTIONAL, + PSIZE_T ReturnLength OPTIONAL) +{ + NTSTATUS Status; + + Status = RtlQueryHeapInformation(HeapHandle, + HeapInformationClass, + HeapInformation, + HeapInformationLength, + ReturnLength); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +HeapSetInformation(HANDLE HeapHandle, + HEAP_INFORMATION_CLASS HeapInformationClass, + PVOID HeapInformation OPTIONAL, + SIZE_T HeapInformationLength OPTIONAL) +{ + NTSTATUS Status; + + Status = RtlSetHeapInformation(HeapHandle, + HeapInformationClass, + HeapInformation, + HeapInformationLength); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + /* * @implemented */ @@ -884,18 +1204,18 @@ GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer) NULL); /* Calculate memory load */ - lpBuffer->dwMemoryLoad = ((DWORD)(BaseCachedSysInfo.NumberOfPhysicalPages - + lpBuffer->dwMemoryLoad = ((DWORD)(BaseStaticServerData->SysInfo.NumberOfPhysicalPages - PerformanceInfo.AvailablePages) * 100) / - BaseCachedSysInfo.NumberOfPhysicalPages; + BaseStaticServerData->SysInfo.NumberOfPhysicalPages; /* Save physical memory */ - PhysicalMemory = BaseCachedSysInfo.NumberOfPhysicalPages * - BaseCachedSysInfo.PageSize; + PhysicalMemory = BaseStaticServerData->SysInfo.NumberOfPhysicalPages * + BaseStaticServerData->SysInfo.PageSize; lpBuffer->ullTotalPhys = PhysicalMemory; /* Now save available physical memory */ PhysicalMemory = PerformanceInfo.AvailablePages * - BaseCachedSysInfo.PageSize; + BaseStaticServerData->SysInfo.PageSize; lpBuffer->ullAvailPhys = PhysicalMemory; /* Query VM and Quota Limits */ @@ -921,11 +1241,11 @@ GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer) lpBuffer->ullAvailPageFile = min(PageFile, QuotaLimits.PagefileLimit - VmCounters.PagefileUsage); - lpBuffer->ullAvailPageFile *= BaseCachedSysInfo.PageSize; + lpBuffer->ullAvailPageFile *= BaseStaticServerData->SysInfo.PageSize; /* Now calculate the total virtual space */ - lpBuffer->ullTotalVirtual = (BaseCachedSysInfo.MaximumUserModeAddress - - BaseCachedSysInfo.MinimumUserModeAddress) + 1; + lpBuffer->ullTotalVirtual = (BaseStaticServerData->SysInfo.MaximumUserModeAddress - + BaseStaticServerData->SysInfo.MinimumUserModeAddress) + 1; /* And finally the avilable virtual space */ lpBuffer->ullAvailVirtual = lpBuffer->ullTotalVirtual - @@ -959,4 +1279,484 @@ GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) } } +/* + * @implemented + */ +HLOCAL +NTAPI +LocalAlloc(UINT uFlags, + SIZE_T dwBytes) +{ + ULONG Flags = 0; + PVOID Ptr = NULL; + HANDLE hMemory; + PBASE_HEAP_HANDLE_ENTRY HandleEntry; + BASE_TRACE_ALLOC(dwBytes, uFlags); + ASSERT(hProcessHeap); + + /* Make sure the flags are valid */ + if (uFlags & ~LMEM_VALID_FLAGS) + { + /* They aren't, fail */ + BASE_TRACE_FAILURE(); + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* Convert ZEROINIT */ + if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; + + /* Check if we're not movable, which means pointer-based heap */ + if (!(uFlags & LMEM_MOVEABLE)) + { + /* Allocate heap for it */ + Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); + BASE_TRACE_ALLOC2(Ptr); + return Ptr; + } + + /* This is heap based, so lock it in first */ + RtlLockHeap(hProcessHeap); + + /* + * Disable locking, enable custom flags, and write the + * movable flag (deprecated) + */ + Flags |= HEAP_NO_SERIALIZE | + HEAP_SETTABLE_USER_VALUE | + BASE_HEAP_FLAG_MOVABLE; + + /* Allocate the handle */ + HandleEntry = BaseHeapAllocEntry(); + if (!HandleEntry) + { + /* Fail */ + hMemory = NULL; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + BASE_TRACE_FAILURE(); + goto Quickie; + } + + /* Get the object and make sure we have size */ + hMemory = &HandleEntry->Object; + if (dwBytes) + { + /* Allocate the actual memory for it */ + Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); + BASE_TRACE_PTR(HandleEntry, Ptr); + if (!Ptr) + { + /* We failed, manually set the allocate flag and free the handle */ + HandleEntry->Flags = RTL_HANDLE_VALID; + BaseHeapFreeEntry(HandleEntry); + + /* For the cleanup case */ + HandleEntry = NULL; + } + else + { + /* All worked well, save our heap entry */ + RtlSetUserValueHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, hMemory); + } + } + +Quickie: + /* Cleanup! First unlock the heap */ + RtlUnlockHeap(hProcessHeap); + + /* Check if a handle was allocated */ + if (HandleEntry) + { + /* Set the pointer and allocated flag */ + HandleEntry->Object = Ptr; + HandleEntry->Flags = RTL_HANDLE_VALID; + if (!Ptr) + { + /* We don't have a valid pointer, but so reuse this handle */ + HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; + } + + /* Check if the handle is discardable */ + if (uFlags & GMEM_DISCARDABLE) + { + /* Save it in the handle entry */ + HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; + } + + /* Check if the handle is moveable */ + if (uFlags & GMEM_MOVEABLE) + { + /* Save it in the handle entry */ + HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE; + } + + /* Set the pointer */ + Ptr = hMemory; + } + + /* Return the pointer */ + return Ptr; +} + +/* + * @implemented + */ +SIZE_T +NTAPI +LocalCompact(UINT dwMinFree) +{ + /* Call the RTL Heap Manager */ + return RtlCompactHeap(hProcessHeap, 0); +} + +/* + * @implemented + */ +UINT +NTAPI +LocalFlags(HLOCAL hMem) +{ + PBASE_HEAP_HANDLE_ENTRY HandleEntry; + HANDLE Handle = NULL; + ULONG Flags = 0; + UINT uFlags = LMEM_INVALID_HANDLE; + + /* Start by locking the heap */ + RtlLockHeap(hProcessHeap); + + /* Check if this is a simple RTL Heap Managed block */ + if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) + { + /* Then we'll query RTL Heap */ + RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags); + BASE_TRACE_PTR(Handle, hMem); + + /* + * Check if RTL Heap didn't find a handle associated with us or + * said that this heap isn't movable, which means something we're + * really not a handle-based heap. + */ + if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) + { + /* Then set the flags to 0 */ + uFlags = 0; + } + else + { + /* Otherwise we're handle-based, so get the internal handle */ + hMem = Handle; + } + } + + /* Check if the handle is actually an entry in our table */ + if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY) + { + /* Then get the entry */ + HandleEntry = BaseHeapGetEntry(hMem); + BASE_TRACE_HANDLE(HandleEntry, hMem); + + /* Make sure it's a valid handle */ + if (BaseHeapValidateEntry(HandleEntry)) + { + /* Get the lock count first */ + uFlags = HandleEntry->LockCount & LMEM_LOCKCOUNT; + + /* Now check if it's discardable */ + if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE) + { + /* Set the Win32 Flag */ + uFlags |= LMEM_DISCARDABLE; + } + + /* Now check if it's discarded */ + if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE) + /* Set the Win32 Flag */ + uFlags |= LMEM_DISCARDED; + } + } + + /* Check if by now, we still haven't gotten any useful flags */ + if (uFlags == LMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE); + + /* All done! Unlock heap and return Win32 Flags */ + RtlUnlockHeap(hProcessHeap); + return uFlags; +} + +/* + * @implemented + */ +HLOCAL +NTAPI +LocalFree(HLOCAL hMem) +{ + /* This is identical to a Global Free */ + return GlobalFree(hMem); +} + +/* + * @implemented + */ +HLOCAL +NTAPI +LocalHandle(LPCVOID pMem) +{ + /* This is identical to a Global Handle */ + return GlobalHandle(pMem); +} + +/* + * @implemented + */ +LPVOID +NTAPI +LocalLock(HLOCAL hMem) +{ + /* This is the same as a GlobalLock, assuming these never change */ + C_ASSERT(LMEM_LOCKCOUNT == GMEM_LOCKCOUNT); + return GlobalLock(hMem); +} + +HLOCAL +NTAPI +LocalReAlloc(HLOCAL hMem, + SIZE_T dwBytes, + UINT uFlags) +{ + PBASE_HEAP_HANDLE_ENTRY HandleEntry; + LPVOID Ptr; + ULONG Flags = 0; + + /* Convert ZEROINIT */ + if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; + + /* If this wasn't a movable heap, then we MUST re-alloc in place */ + if (!(uFlags & LMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY; + + /* Lock the heap and disable built-in locking in the RTL Heap funcitons */ + RtlLockHeap(hProcessHeap); + Flags |= HEAP_NO_SERIALIZE; + + /* Check if this is a simple handle-based block */ + if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) + { + /* Get the entry */ + HandleEntry = BaseHeapGetEntry(hMem); + BASE_TRACE_HANDLE(HandleEntry, hMem); + + /* Make sure the handle is valid */ + if (!BaseHeapValidateEntry(HandleEntry)) + { + /* Fail */ + BASE_TRACE_FAILURE(); + SetLastError(ERROR_INVALID_HANDLE); + hMem = NULL; + } + else if (uFlags & LMEM_MODIFY) + { + /* User is changing flags... check if the memory was discardable */ + if (uFlags & LMEM_DISCARDABLE) + { + /* Then set the flag */ + HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; + } + else + { + /* Otherwise, remove the flag */ + HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE; + } + } + else + { + /* Otherwise, get the object and check if we have no size */ + Ptr = HandleEntry->Object; + if (!dwBytes) + { + /* Clear the handle and check for a pointer */ + hMem = NULL; + if (Ptr) + { + /* Make sure the handle isn't locked */ + if ((uFlags & LMEM_MOVEABLE) && !(HandleEntry->LockCount)) + { + /* Free the current heap */ + RtlFreeHeap(hProcessHeap, Flags, Ptr); + + /* Free the handle */ + HandleEntry->Object = NULL; + HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; + + /* Get the object pointer */ + hMem = &HandleEntry->Object; + } + } + else + { + /* Otherwise just return the object pointer */ + hMem = &HandleEntry->Object; + } + } + else + { + /* Otherwise, we're allocating, so set the new flags needed */ + Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE; + if (!Ptr) + { + /* We don't have a base, so allocate one */ + Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); + BASE_TRACE_ALLOC2(Ptr); + if (Ptr) + { + /* Allocation succeeded, so save our entry */ + RtlSetUserValueHeap(hProcessHeap, + HEAP_NO_SERIALIZE, + Ptr, + hMem); + } + } + else + { + /* + * If it's not movable or currently locked, we MUST allocate + * in-place! + */ + if (!(uFlags & LMEM_MOVEABLE) && (HandleEntry->LockCount)) + { + /* Set the flag */ + Flags |= HEAP_REALLOC_IN_PLACE_ONLY; + } + else + { + /* Otherwise clear the flag if we set it previously */ + Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY; + } + + /* And do the re-allocation */ + Ptr = RtlReAllocateHeap(hProcessHeap, Flags, Ptr, dwBytes); + } + + /* Make sure we have a pointer by now */ + if (Ptr) + { + /* Write it in the handle entry and mark it in use */ + HandleEntry->Object = Ptr; + HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE; + } + else + { + /* Otherwise we failed */ + hMem = NULL; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + } + } + } + else if (!(uFlags & LMEM_MODIFY)) + { + /* Otherwise, this is a simple RTL Managed Heap, so just call it */ + hMem = RtlReAllocateHeap(hProcessHeap, + Flags | HEAP_NO_SERIALIZE, + hMem, + dwBytes); + if (!hMem) + { + /* Fail */ + BASE_TRACE_FAILURE(); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + } + + /* All done, unlock the heap and return the pointer */ + RtlUnlockHeap(hProcessHeap); + return hMem; +} + +/* + * @implemented + */ +SIZE_T +WINAPI +LocalShrink(HLOCAL hMem, + UINT cbNewSize) +{ + /* Call RTL */ + return RtlCompactHeap(hProcessHeap, 0); +} + +/* + * @implemented + */ +SIZE_T +NTAPI +LocalSize(HLOCAL hMem) +{ + /* This is the same as a Global Size */ + return GlobalSize(hMem); +} + +/* + * @implemented + */ +BOOL +NTAPI +LocalUnlock(HLOCAL hMem) +{ + PBASE_HEAP_HANDLE_ENTRY HandleEntry; + BOOL RetVal = TRUE; + + /* Check if this was a simple allocated heap entry */ + if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) + { + /* Fail, because LocalUnlock is not supported on LMEM_FIXED allocations */ + SetLastError(ERROR_NOT_LOCKED); + return FALSE; + } + + /* Otherwise, lock the heap */ + RtlLockHeap(hProcessHeap); + + /* Get the handle entry */ + HandleEntry = BaseHeapGetEntry(hMem); + BASE_TRACE_HANDLE(HandleEntry, hMem); + + _SEH2_TRY + { + /* Make sure it's valid */ + if (!BaseHeapValidateEntry(HandleEntry)) + { + /* It's not, fail */ + BASE_TRACE_FAILURE(); + SetLastError(ERROR_INVALID_HANDLE); + RetVal = FALSE; + } + else + { + /* Otherwise, decrement lock count, unless we're already at 0*/ + if (!HandleEntry->LockCount--) + { + /* In which case we simply lock it back and fail */ + HandleEntry->LockCount++; + SetLastError(ERROR_NOT_LOCKED); + RetVal = FALSE; + } + else if (!HandleEntry->LockCount) + { + /* Nothing to unlock */ + SetLastError(NO_ERROR); + RetVal = FALSE; + } + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_PARAMETER); + RetVal = FALSE; + } + _SEH2_END + + /* All done. Unlock the heap and return the pointer */ + RtlUnlockHeap(hProcessHeap); + return RetVal; +} + /* EOF */ diff --git a/dll/win32/kernel32/thread/i386/fiber.S b/dll/win32/kernel32/client/i386/fiber.S similarity index 84% rename from dll/win32/kernel32/thread/i386/fiber.S rename to dll/win32/kernel32/client/i386/fiber.S index bf88c468487..d8bc8f28a3b 100644 --- a/dll/win32/kernel32/thread/i386/fiber.S +++ b/dll/win32/kernel32/client/i386/fiber.S @@ -10,50 +10,62 @@ #include #include +EXTERN _BaseThreadStartup@8:PROC + .code +PUBLIC _BaseFiberStartup@0 +.PROC BaseFiberStartup@0 + /* Frame pointer is zeroed */ + FPO 0, 0, 0, 0, 0, FRAME_FPO + + /* Get the fiber data */ + mov eax, fs:[TEB_FIBER_DATA] + + push dword ptr [eax+FIBER_CONTEXT_EBX] /* Parameter */ + push dword ptr [eax+FIBER_CONTEXT_EAX] /* Start Address */ + call _BaseThreadStartup@8 +.ENDP BaseFiberStartup@0 + + PUBLIC _SwitchToFiber@4 _SwitchToFiber@4: /* Get the TEB */ mov edx, fs:[TEB_SELF] - + /* Get the Fiber */ mov eax, [edx+TEB_FIBER_DATA] - + /* Save the non-volatile registers */ mov [eax+FIBER_CONTEXT_EBX], ebx mov [eax+FIBER_CONTEXT_ESI], esi mov [eax+FIBER_CONTEXT_EDI], edi mov [eax+FIBER_CONTEXT_EBP], ebp - /* Save the return address */ - mov ebx, [esp] - mov [eax+FIBER_CONTEXT_EIP], ebx - /* Check if we're to save FPU State */ cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL OR CONTEXT_FLOATING_POINT jnz NoFpuStateSave - + /* Save the FPU State (Status and Control)*/ fstsw [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD] - fstcw [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD] - + fnstcw [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD] + /* Check if the CPU supports SIMD MXCSR State Save */ - cmp byte ptr ds:[PROCESSOR_FEATURE_FXSR], 0 + cmp byte ptr ds:[PF_XMMI_INSTRUCTIONS_AVAILABLE], 1 jnz NoFpuStateSave stmxcsr [eax+FIBER_CONTEXT_DR6] - + NoFpuStateSave: /* Save stack since we're not touching it anymore */ mov [eax+FIBER_CONTEXT_ESP], esp - + /* Transfer some data from the TEB */ mov ecx, [edx+TEB_FLS_DATA] mov [eax+FIBER_FLS_DATA], ecx mov ecx, [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER] mov [eax+FIBER_ACTIVATION_CONTEXT_STACK], ecx - + /* Transfer some data related to the Stack */ mov ecx, [edx+TEB_EXCEPTION_LIST] mov [eax+FIBER_EXCEPTION_LIST], ecx @@ -61,11 +73,11 @@ NoFpuStateSave: mov [eax+FIBER_STACK_LIMIT], ecx mov ecx, [edx+TEB_GUARANTEED_STACK_BYTES] mov [eax+FIBER_GUARANTEED_STACK_BYTES], ecx - + /* Switch to the new fiber */ mov ecx, [esp+4] mov [edx+TEB_FIBER_DATA], ecx - + /* Switch Fiber Data */ mov esi, [ecx+FIBER_EXCEPTION_LIST] mov [edx+TEB_EXCEPTION_LIST], esi @@ -79,34 +91,34 @@ NoFpuStateSave: mov [edx+TEB_GUARANTEED_STACK_BYTES], esi mov esi, [ecx+FIBER_ACTIVATION_CONTEXT_STACK] mov [edx+TEB_ACTIVATION_CONTEXT_STACK_POINTER], esi - + /* Restore FPU State */ cmp dword ptr [eax+FIBER_CONTEXT_FLAGS], CONTEXT_FULL OR CONTEXT_FLOATING_POINT jnz NoFpuStateRestore - + /* Check if the Status Word Changed */ mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD] cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_STATUS_WORD] jnz StatusWordChanged - + /* Check if the Control Word Changed */ mov esi, [eax+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD] cmp si, word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD] jz ControlWordEqual - + StatusWordChanged: /* Load the new one */ mov word ptr [ecx+FIBER_CONTEXT_FLOAT_SAVE_TAG_WORD], HEX(0FFFF) fldenv [ecx+FIBER_CONTEXT_FLOAT_SAVE_CONTROL_WORD] - + ControlWordEqual: /* Load the new one */ - cmp byte ptr ds:[PROCESSOR_FEATURE_FXSR], 0 + cmp byte ptr ds:[PF_XMMI_INSTRUCTIONS_AVAILABLE], 1 jnz NoFpuStateRestore ldmxcsr [ecx+FIBER_CONTEXT_DR6] - + NoFpuStateRestore: /* Restore non-volatile registers */ @@ -115,13 +127,14 @@ NoFpuStateRestore: mov ebx, [ecx+FIBER_CONTEXT_EBX] mov ebp, [ecx+FIBER_CONTEXT_EBP] mov esp, [ecx+FIBER_CONTEXT_ESP] - + /* Restore FLS Data */ mov eax, [ecx+FIBER_FLS_DATA] mov [edx+TEB_FLS_DATA], eax /* Jump to new fiber */ - jmp dword ptr [ecx+FIBER_CONTEXT_EIP] - + mov esp, [ecx+FIBER_CONTEXT_ESP] + ret 4 END + /* EOF */ diff --git a/dll/win32/kernel32/thread/i386/thread.S b/dll/win32/kernel32/client/i386/thread.S similarity index 97% rename from dll/win32/kernel32/thread/i386/thread.S rename to dll/win32/kernel32/client/i386/thread.S index a07bcb2e60e..f6964572246 100644 --- a/dll/win32/kernel32/thread/i386/thread.S +++ b/dll/win32/kernel32/client/i386/thread.S @@ -7,6 +7,7 @@ */ #include +#include .code @@ -14,8 +15,6 @@ EXTERN _BaseThreadStartup@8:PROC EXTERN _BaseProcessStartup@4:PROC PUBLIC _BaseThreadStartupThunk@0 -PUBLIC _BaseProcessStartThunk@0 - _BaseThreadStartupThunk@0: /* Start out fresh */ @@ -26,8 +25,9 @@ _BaseThreadStartupThunk@0: push 0 /* Return EIP */ jmp _BaseThreadStartup@8 -_BaseProcessStartThunk@0: +PUBLIC _BaseProcessStartThunk@0 +_BaseProcessStartThunk@0: /* Start out fresh */ xor ebp, ebp @@ -35,5 +35,7 @@ _BaseProcessStartThunk@0: push 0 /* Return EIP */ jmp _BaseProcessStartup@4 + END + /* EOF */ diff --git a/dll/win32/kernel32/process/job.c b/dll/win32/kernel32/client/job.c similarity index 69% rename from dll/win32/kernel32/process/job.c rename to dll/win32/kernel32/client/job.c index 43a77c905f9..da5ee9b08bd 100644 --- a/dll/win32/kernel32/process/job.c +++ b/dll/win32/kernel32/client/job.c @@ -18,97 +18,30 @@ /* FUNCTIONS ****************************************************************/ - /* * @implemented */ HANDLE WINAPI -CreateJobObjectA(LPSECURITY_ATTRIBUTES lpJobAttributes, - LPCSTR lpName) +CreateJobObjectA(IN LPSECURITY_ATTRIBUTES lpJobAttributes, + IN LPCSTR lpName) { - HANDLE hJob; - ANSI_STRING AnsiName; - UNICODE_STRING UnicodeName; - - if (lpName != NULL) - { - NTSTATUS Status; - - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - } - - hJob = CreateJobObjectW(lpJobAttributes, - ((lpName != NULL) ? UnicodeName.Buffer : NULL)); - - if (lpName != NULL) - { - RtlFreeUnicodeString(&UnicodeName); - } - - return hJob; + /* Call the W(ide) function */ + ConvertWin32AnsiObjectApiToUnicodeApi(JobObject, lpName, lpJobAttributes); } - /* * @implemented */ HANDLE WINAPI -CreateJobObjectW(LPSECURITY_ATTRIBUTES lpJobAttributes, - LPCWSTR lpName) +CreateJobObjectW(IN LPSECURITY_ATTRIBUTES lpJobAttributes, + IN LPCWSTR lpName) { - UNICODE_STRING JobName; - OBJECT_ATTRIBUTES ObjectAttributes; - ULONG Attributes = 0; - PVOID SecurityDescriptor; - HANDLE hJob; - NTSTATUS Status; - - if (lpName != NULL) - { - RtlInitUnicodeString(&JobName, lpName); - } - - if (lpJobAttributes != NULL) - { - if (lpJobAttributes->bInheritHandle) - { - Attributes |= OBJ_INHERIT; - } - - SecurityDescriptor = lpJobAttributes->lpSecurityDescriptor; - } - else - { - SecurityDescriptor = NULL; - } - - InitializeObjectAttributes(&ObjectAttributes, - ((lpName != NULL) ? &JobName : NULL), - Attributes, - NULL, - SecurityDescriptor); - - Status = NtCreateJobObject(&hJob, - JOB_OBJECT_ALL_ACCESS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return NULL; - } - - return hJob; + /* Create the NT object */ + CreateNtObjectFromWin32Api(JobObject, JobObject, JOB, lpJobAttributes, lpName); } - /* * @implemented */ @@ -118,35 +51,8 @@ OpenJobObjectW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName) { - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING JobName; - HANDLE hJob; - NTSTATUS Status; - - if (lpName == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - RtlInitUnicodeString(&JobName, lpName); - - InitializeObjectAttributes(&ObjectAttributes, - &JobName, - (bInheritHandle ? OBJ_INHERIT : 0), - NULL, - NULL); - - Status = NtOpenJobObject(&hJob, - dwDesiredAccess, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return NULL; - } - - return hJob; + /* Open the NT object */ + OpenNtObjectFromWin32Api(JobObject, dwDesiredAccess, bInheritHandle, lpName); } @@ -159,31 +65,8 @@ OpenJobObjectA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName) { - ANSI_STRING AnsiName; - UNICODE_STRING UnicodeName; - HANDLE hJob; - NTSTATUS Status; - - if (lpName == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - hJob = OpenJobObjectW(dwDesiredAccess, - bInheritHandle, - UnicodeName.Buffer); - - RtlFreeUnicodeString(&UnicodeName); - return hJob; + /* Call the W(ide) function */ + ConvertOpenWin32AnsiObjectApiToUnicodeApi(JobObject, dwDesiredAccess, bInheritHandle, lpName); } @@ -205,7 +88,7 @@ IsProcessInJob(HANDLE ProcessHandle, return TRUE; } - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -223,7 +106,7 @@ AssignProcessToJobObject(HANDLE hJob, Status = NtAssignProcessToJobObject(hJob, hProcess); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -308,7 +191,7 @@ QueryInformationJobObject(HANDLE hJob, return TRUE; } - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -403,7 +286,7 @@ SetInformationJobObject(HANDLE hJob, cbJobObjectInformationLength); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -424,11 +307,25 @@ TerminateJobObject(HANDLE hJob, Status = NtTerminateJobObject(hJob, uExitCode); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } return TRUE; } +/* + * @unimplemented + */ +BOOL +WINAPI +CreateJobSet ( + ULONG NumJob, + PJOB_SET_ARRAY UserJobSet, + ULONG Flags) +{ + STUB; + return 0; +} + /* EOF */ diff --git a/dll/win32/kernel32/client/loader.c b/dll/win32/kernel32/client/loader.c new file mode 100644 index 00000000000..b600b8c2fc3 --- /dev/null +++ b/dll/win32/kernel32/client/loader.c @@ -0,0 +1,1200 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT : ReactOS system libraries + * MODULE : kernel32.dll + * FILE : reactos/dll/win32/kernel32/misc/ldr.c + * AUTHOR : Aleksey Bragin + */ + +#include + +#define NDEBUG +#include + +typedef struct tagLOADPARMS32 { + LPSTR lpEnvAddress; + LPSTR lpCmdLine; + WORD wMagicValue; + WORD wCmdShow; + DWORD dwReserved; +} LOADPARMS32; + +extern BOOLEAN InWindows; +extern WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle; + +#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR 1 +#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS 2 +#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE 3 + +VOID +NTAPI +BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry, + IN PVOID Context, + OUT BOOLEAN *StopEnumeration); + +/* FUNCTIONS ****************************************************************/ + +DWORD +WINAPI +BasepGetModuleHandleExParameterValidation(DWORD dwFlags, + LPCWSTR lpwModuleName, + HMODULE *phModule) +{ + /* Set phModule to 0 if it's not a NULL pointer */ + if (phModule) *phModule = 0; + + /* Check for invalid flags combination */ + if (dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) || + ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) && + (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) || + (!lpwModuleName && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) + ) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER_1); + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR; + } + + /* Check 2nd parameter */ + if (!phModule) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER_2); + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR; + } + + /* Return what we have according to the module name */ + if (lpwModuleName) + { + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE; + } + + /* No name given, so put ImageBaseAddress there */ + *phModule = (HMODULE)NtCurrentPeb()->ImageBaseAddress; + + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS; +} + +PVOID +WINAPI +BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile) +{ + /* If no handle is provided - use current image base address */ + if (!hModule) return NtCurrentPeb()->ImageBaseAddress; + + /* Check if it's a normal or a datafile one */ + if (LDR_IS_DATAFILE(hModule) && !AsDataFile) + return NULL; + + /* It'a a normal DLL, just return its handle */ + return hModule; +} + +/** + * @name GetDllLoadPath + * + * Internal function to compute the load path to use for a given dll. + * + * @remarks Returned pointer must be freed by caller. + */ + +LPWSTR +GetDllLoadPath(LPCWSTR lpModule) +{ + ULONG Pos = 0, Length = 0; + PWCHAR EnvironmentBufferW = NULL; + LPCWSTR lpModuleEnd = NULL; + UNICODE_STRING ModuleName; + DWORD LastError = GetLastError(); /* GetEnvironmentVariable changes LastError */ + + // FIXME: This function is used only by SearchPathW, and is deprecated and will be deleted ASAP. + + if ((lpModule != NULL) && (wcslen(lpModule) > 2) && (lpModule[1] == ':')) + { + lpModuleEnd = lpModule + wcslen(lpModule); + } + else + { + ModuleName = NtCurrentPeb()->ProcessParameters->ImagePathName; + lpModule = ModuleName.Buffer; + lpModuleEnd = lpModule + (ModuleName.Length / sizeof(WCHAR)); + } + + if (lpModule != NULL) + { + while (lpModuleEnd > lpModule && *lpModuleEnd != L'/' && + *lpModuleEnd != L'\\' && *lpModuleEnd != L':') + { + --lpModuleEnd; + } + Length = (lpModuleEnd - lpModule) + 1; + } + + Length += GetCurrentDirectoryW(0, NULL); + Length += GetDllDirectoryW(0, NULL); + Length += GetSystemDirectoryW(NULL, 0); + Length += GetWindowsDirectoryW(NULL, 0); + Length += GetEnvironmentVariableW(L"PATH", NULL, 0); + + EnvironmentBufferW = RtlAllocateHeap(RtlGetProcessHeap(), 0, + Length * sizeof(WCHAR)); + if (EnvironmentBufferW == NULL) + { + return NULL; + } + + if (lpModule) + { + RtlCopyMemory(EnvironmentBufferW, lpModule, + (lpModuleEnd - lpModule) * sizeof(WCHAR)); + Pos += lpModuleEnd - lpModule; + EnvironmentBufferW[Pos++] = L';'; + } + + Pos += GetCurrentDirectoryW(Length, EnvironmentBufferW + Pos); + EnvironmentBufferW[Pos++] = L';'; + Pos += GetDllDirectoryW(Length - Pos, EnvironmentBufferW + Pos); + EnvironmentBufferW[Pos++] = L';'; + Pos += GetSystemDirectoryW(EnvironmentBufferW + Pos, Length - Pos); + EnvironmentBufferW[Pos++] = L';'; + Pos += GetWindowsDirectoryW(EnvironmentBufferW + Pos, Length - Pos); + EnvironmentBufferW[Pos++] = L';'; + Pos += GetEnvironmentVariableW(L"PATH", EnvironmentBufferW + Pos, Length - Pos); + + SetLastError(LastError); + return EnvironmentBufferW; +} + +/* + * @implemented + */ +BOOL +WINAPI +DisableThreadLibraryCalls( + IN HMODULE hLibModule) +{ + NTSTATUS Status; + + /* Disable thread library calls */ + Status = LdrDisableThreadCalloutsForDll((PVOID)hLibModule); + + /* If it wasn't success - set last error and return failure */ + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + /* Return success */ + return TRUE; +} + + +/* + * @implemented + */ +HINSTANCE +WINAPI +LoadLibraryA(LPCSTR lpLibFileName) +{ + LPSTR PathBuffer; + UINT Len; + HINSTANCE Result; + + /* Treat twain_32.dll in a special way (what a surprise...) */ + if (lpLibFileName && !_strcmpi(lpLibFileName, "twain_32.dll")) + { + /* Allocate space for the buffer */ + PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH); + if (PathBuffer) + { + /* Get windows dir in this buffer */ + Len = GetWindowsDirectoryA(PathBuffer, MAX_PATH - 13); /* 13 is sizeof of '\\twain_32.dll' */ + if (Len && Len < (MAX_PATH - 13)) + { + /* We successfully got windows directory. Concatenate twain_32.dll to it */ + strncat(PathBuffer, "\\twain_32.dll", 13); + + /* And recursively call ourselves with a new string */ + Result = LoadLibraryA(PathBuffer); + + /* If it was successful - free memory and return result */ + if (Result) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + return Result; + } + } + + /* Free allocated buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + } + } + + /* Call the Ex version of the API */ + return LoadLibraryExA(lpLibFileName, 0, 0); +} + +/* + * @implemented + */ +HINSTANCE +WINAPI +LoadLibraryExA(LPCSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) +{ + PUNICODE_STRING FileNameW; + + /* Convert file name to unicode */ + if (!(FileNameW = Basep8BitStringToStaticUnicodeString(lpLibFileName))) + return NULL; + + /* And call W version of the API */ + return LoadLibraryExW(FileNameW->Buffer, hFile, dwFlags); +} + +/* + * @implemented + */ +HINSTANCE +WINAPI +LoadLibraryW(LPCWSTR lpLibFileName) +{ + /* Call Ex version of the API */ + return LoadLibraryExW (lpLibFileName, 0, 0); +} + + +static +NTSTATUS +BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule) +{ + WCHAR FilenameW[MAX_PATH]; + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hMapping; + NTSTATUS Status; + PVOID lpBaseAddress = NULL; + SIZE_T ViewSize = 0; + //PUNICODE_STRING OriginalName; + //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL"); + + /* Zero out handle value */ + *hModule = 0; + + DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path, Name, hModule); + + /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + Name, + &dotDLL, + RedirName, + RedirName2, + &OriginalName2, + NULL, + NULL, + NULL);*/ + + /* Try to search for it */ + if (!SearchPathW(Path, + Name, + L".DLL", + sizeof(FilenameW) / sizeof(FilenameW[0]), + FilenameW, + NULL)) + { + /* Return last status value directly */ + return NtCurrentTeb()->LastStatusValue; + } + + /* Open this file we found */ + hFile = CreateFileW(FilenameW, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + 0); + + /* If opening failed - return last status value */ + if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue; + + /* Create file mapping */ + hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + + /* Close the file handle */ + CloseHandle(hFile); + + /* If creating file mapping failed - return last status value */ + if (!hMapping) return NtCurrentTeb()->LastStatusValue; + + /* Map view of section */ + Status = NtMapViewOfSection(hMapping, + NtCurrentProcess(), + &lpBaseAddress, + 0, + 0, + 0, + &ViewSize, + ViewShare, + 0, + PAGE_READONLY); + + /* Close handle to the section */ + CloseHandle(hMapping); + + /* If mapping view of section failed - return last status value */ + if (!NT_SUCCESS(Status)) return NtCurrentTeb()->LastStatusValue; + + /* Make sure it's a valid PE file */ + if (!RtlImageNtHeader(lpBaseAddress)) + { + /* Unmap the view and return failure status */ + UnmapViewOfFile(lpBaseAddress); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Set low bit of handle to indicate datafile module */ + *hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1); + + /* Load alternate resource module */ + //LdrLoadAlternateResourceModule(*hModule, FilenameW); + + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +HINSTANCE +WINAPI +LoadLibraryExW(LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) +{ + UNICODE_STRING DllName; + HINSTANCE hInst; + NTSTATUS Status; + PWSTR SearchPath; + ULONG DllCharacteristics = 0; + BOOL FreeString = FALSE; + + /* Check for any flags LdrLoadDll might be interested in */ + if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) + { + /* Tell LDR to treat it as an EXE */ + DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE; + } + + /* Build up a unicode dll name from null-terminated string */ + RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); + + /* Lazy-initialize BasepExeLdrEntry */ + if (!BasepExeLdrEntry) + LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress); + + /* Check if that module is our exe*/ + if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && + DllName.Length == BasepExeLdrEntry->FullDllName.Length) + { + /* Lengths match and it's not a datafile, so perform name comparison */ + if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE)) + { + /* That's us! */ + return BasepExeLdrEntry->DllBase; + } + } + + /* Check for trailing spaces and remove them if necessary */ + if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') + { + RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); + while (DllName.Length > sizeof(WCHAR) && + DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') + { + DllName.Length -= sizeof(WCHAR); + } + DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; + FreeString = TRUE; + } + + /* Compute the load path */ + SearchPath = BasepGetDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? (LPWSTR)lpLibFileName : NULL, + NULL); + + if (!SearchPath) + { + /* Getting DLL path failed, so set last error, free mem and return */ + BaseSetLastNTError(STATUS_NO_MEMORY); + if (FreeString) RtlFreeUnicodeString(&DllName); + return NULL; + } + + _SEH2_TRY + { + if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) + { + /* If the image is loaded as a datafile, try to get its handle */ + Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst); + if (!NT_SUCCESS(Status)) + { + /* It's not loaded yet - so load it up */ + Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); + _SEH2_YIELD(goto done;) + } + } + + /* Call the API Properly */ + Status = LdrLoadDll(SearchPath, + &DllCharacteristics, + &DllName, + (PVOID*)&hInst); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } _SEH2_END + + +done: + /* Free SearchPath buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); + + /* Free DllName string if it was dynamically allocated */ + if (FreeString) RtlFreeUnicodeString(&DllName); + + /* Set last error in failure case */ + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + /* Return loaded module handle */ + return hInst; +} + + +/* + * @implemented + */ +FARPROC +WINAPI +GetProcAddress(HMODULE hModule, LPCSTR lpProcName) +{ + ANSI_STRING ProcedureName, *ProcNamePtr = NULL; + FARPROC fnExp = NULL; + NTSTATUS Status; + PVOID hMapped; + ULONG Ordinal = 0; + + if (HIWORD(lpProcName) != 0) + { + /* Look up by name */ + RtlInitAnsiString(&ProcedureName, (LPSTR)lpProcName); + ProcNamePtr = &ProcedureName; + } + else + { + /* Look up by ordinal */ + Ordinal = (ULONG)lpProcName; + } + + /* Map provided handle */ + hMapped = BasepMapModuleHandle(hModule, FALSE); + + /* Get the proc address */ + Status = LdrGetProcedureAddress(hMapped, + ProcNamePtr, + Ordinal, + (PVOID*)&fnExp); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + /* Check for a special case when returned pointer is + the same as iamge's base address */ + if (fnExp == hMapped) + { + /* Set correct error code */ + if (HIWORD(lpProcName) != 0) + BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND); + else + BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND); + + return NULL; + } + + /* All good, return procedure pointer */ + return fnExp; +} + + +/* + * @implemented + */ +BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) +{ + NTSTATUS Status; + PIMAGE_NT_HEADERS NtHeaders; + + if (LDR_IS_DATAFILE(hLibModule)) + { + // FIXME: This SEH should go inside RtlImageNtHeader instead + _SEH2_TRY + { + /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */ + NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + NtHeaders = NULL; + } _SEH2_END + + if (NtHeaders) + { + /* Unmap view */ + Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); + + /* Unload alternate resource module */ + LdrUnloadAlternateResourceModule(hLibModule); + } + else + Status = STATUS_INVALID_IMAGE_FORMAT; + } + else + { + /* Just unload it */ + Status = LdrUnloadDll((PVOID)hLibModule); + } + + /* Check what kind of status we got */ + if (!NT_SUCCESS(Status)) + { + /* Set last error */ + BaseSetLastNTError(Status); + + /* Return failure */ + return FALSE; + } + + /* Return success */ + return TRUE; +} + + +/* + * @implemented + */ +VOID +WINAPI +FreeLibraryAndExitThread(HMODULE hLibModule, + DWORD dwExitCode) +{ + NTSTATUS Status; + + if (LDR_IS_DATAFILE(hLibModule)) + { + /* This is a LOAD_LIBRARY_AS_DATAFILE module */ + if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1))) + { + /* Unmap view */ + Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); + + /* Unload alternate resource module */ + LdrUnloadAlternateResourceModule(hLibModule); + } + } + else + { + /* Just unload it */ + Status = LdrUnloadDll((PVOID)hLibModule); + } + + /* Exit thread */ + ExitThread(dwExitCode); +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetModuleFileNameA(HINSTANCE hModule, + LPSTR lpFilename, + DWORD nSize) +{ + UNICODE_STRING FilenameW; + ANSI_STRING FilenameA; + NTSTATUS Status; + DWORD Length = 0, LengthToCopy; + + /* Allocate a unicode buffer */ + FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR)); + if (!FilenameW.Buffer) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return 0; + } + + /* Call unicode API */ + FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) * sizeof(WCHAR); + FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR); + + if (FilenameW.Length) + { + /* Convert to ansi string */ + Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE); + if (!NT_SUCCESS(Status)) + { + /* Set last error, free string and retun failure */ + BaseSetLastNTError(Status); + RtlFreeUnicodeString(&FilenameW); + return 0; + } + + /* Calculate size to copy */ + Length = min(nSize, FilenameA.Length); + + /* Include terminating zero */ + if (nSize > Length) + LengthToCopy = Length + 1; + else + LengthToCopy = nSize; + + /* Now copy back to the caller amount he asked */ + RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy); + + /* Free ansi filename */ + RtlFreeAnsiString(&FilenameA); + } + + /* Free unicode filename */ + RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer); + + /* Return length copied */ + return Length; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetModuleFileNameW(HINSTANCE hModule, + LPWSTR lpFilename, + DWORD nSize) +{ + PLIST_ENTRY ModuleListHead, Entry; + PLDR_DATA_TABLE_ENTRY Module; + ULONG Length = 0; + ULONG Cookie; + PPEB Peb; + + hModule = BasepMapModuleHandle(hModule, FALSE); + + /* Upscale nSize from chars to bytes */ + nSize *= sizeof(WCHAR); + + _SEH2_TRY + { + /* We don't use per-thread cur dir now */ + //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib; + + Peb = NtCurrentPeb (); + + /* Acquire a loader lock */ + LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie); + + /* Traverse the module list */ + ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + + /* Check if this is the requested module */ + if (Module->DllBase == (PVOID)hModule) + { + /* Calculate size to copy */ + Length = min(nSize, Module->FullDllName.MaximumLength); + + /* Copy contents */ + RtlMoveMemory(lpFilename, Module->FullDllName.Buffer, Length); + + /* Subtract a terminating zero */ + if (Length == Module->FullDllName.MaximumLength) + Length -= sizeof(WCHAR); + + /* Break out of the loop */ + break; + } + + /* Advance to the next entry */ + Entry = Entry->Flink; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + BaseSetLastNTError(_SEH2_GetExceptionCode()); + Length = 0; + } _SEH2_END + + /* Release the loader lock */ + LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + + return Length / sizeof(WCHAR); +} + +HMODULE +WINAPI +GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName) +{ + NTSTATUS Status; + PVOID Module; + LPWSTR DllPath; + + /* Try to get a handle with a magic value of 1 for DllPath */ + Status = LdrGetDllHandle((LPWSTR)1, NULL, ModuleName, &Module); + + /* If that succeeded - we're done */ + if (NT_SUCCESS(Status)) return Module; + + /* If not, then the path should be computed */ + DllPath = BasepGetDllPath(NULL, 0); + + /* Call LdrGetHandle() again providing the computed DllPath + and wrapped into SEH */ + _SEH2_TRY + { + Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Fail with the SEH error */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + /* Free the DllPath */ + RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath); + + /* In case of error set last win32 error and return NULL */ + if (!NT_SUCCESS(Status)) + { + DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName, Status); + BaseSetLastNTError(Status); + Module = 0; + } + + /* Return module */ + return (HMODULE)Module; +} + +BOOLEAN +WINAPI +BasepGetModuleHandleExW(BOOLEAN NoLock, DWORD dwPublicFlags, LPCWSTR lpwModuleName, HMODULE *phModule) +{ + DWORD Cookie; + NTSTATUS Status = STATUS_SUCCESS, Status2; + HANDLE hModule = 0; + UNICODE_STRING ModuleNameU; + DWORD dwValid; + BOOLEAN Redirected = FALSE; // FIXME + + /* Validate parameters */ + dwValid = BasepGetModuleHandleExParameterValidation(dwPublicFlags, lpwModuleName, phModule); + ASSERT(dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE); + + /* Acquire lock if necessary */ + if (!NoLock) + { + Status = LdrLockLoaderLock(0, NULL, &Cookie); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + BaseSetLastNTError(Status); + if (phModule) *phModule = 0; + return Status; + } + } + + if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) + { + /* Create a unicode string out of module name */ + RtlInitUnicodeString(&ModuleNameU, lpwModuleName); + + // FIXME: Do some redirected DLL stuff? + if (Redirected) + { + UNIMPLEMENTED; + } + + if (!hModule) + { + hModule = GetModuleHandleForUnicodeString(&ModuleNameU); + if (!hModule) + { + /* Last error is already set, so just return failure by setting status */ + Status = STATUS_DLL_NOT_FOUND; + goto quickie; + } + } + } + else + { + /* Perform Pc to file header to get module instance */ + hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpwModuleName, + (PVOID*)&hModule); + + /* Check if it succeeded */ + if (!hModule) + { + /* Set "dll not found" status and quit */ + Status = STATUS_DLL_NOT_FOUND; + goto quickie; + } + } + + /* Check if changing reference is not forbidden */ + if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) + { + /* Add reference to this DLL */ + Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_ADDREF_DLL_PIN : 0, + hModule); + } + + /* Set last error in case of failure */ + if (!NT_SUCCESS(Status)) + BaseSetLastNTError(Status); + +quickie: + /* Unlock loader lock if it was acquired */ + if (!NoLock) + { + Status2 = LdrUnlockLoaderLock(0, Cookie); + ASSERT(NT_SUCCESS(Status2)); + } + + /* Set the module handle to the caller */ + if (phModule) *phModule = hModule; + + /* Return TRUE on success and FALSE otherwise */ + return NT_SUCCESS(Status); +} + +/* + * @implemented + */ +HMODULE +WINAPI +GetModuleHandleA(LPCSTR lpModuleName) +{ + PUNICODE_STRING ModuleNameW; + PTEB pTeb = NtCurrentTeb(); + + /* Check if we have no name to convert */ + if (!lpModuleName) + return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress); + + /* Convert module name to unicode */ + ModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName); + + /* Call W version if conversion was successful */ + if (ModuleNameW) + return GetModuleHandleW(ModuleNameW->Buffer); + + /* Return failure */ + return 0; +} + + +/* + * @implemented + */ +HMODULE +WINAPI +GetModuleHandleW(LPCWSTR lpModuleName) +{ + HMODULE hModule; + NTSTATUS Status; + + /* If current module is requested - return it right away */ + if (!lpModuleName) + return ((HMODULE)NtCurrentPeb()->ImageBaseAddress); + + /* Use common helper routine */ + Status = BasepGetModuleHandleExW(TRUE, + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + lpModuleName, + &hModule); + + /* If it wasn't successful - return 0 */ + if (!NT_SUCCESS(Status)) hModule = 0; + + /* Return the handle */ + return hModule; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetModuleHandleExW(IN DWORD dwFlags, + IN LPCWSTR lpwModuleName OPTIONAL, + OUT HMODULE* phModule) +{ + NTSTATUS Status; + DWORD dwValid; + BOOL Ret = FALSE; + + /* Validate parameters */ + dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule); + + /* If result is invalid parameter - return failure */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE; + + /* If result is 2, there is no need to do anything - return success. */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE; + + /* Use common helper routine */ + Status = BasepGetModuleHandleExW(FALSE, + dwFlags, + lpwModuleName, + phModule); + + /* Return TRUE in case of success */ + if (NT_SUCCESS(Status)) Ret = TRUE; + + return Ret; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetModuleHandleExA(IN DWORD dwFlags, + IN LPCSTR lpModuleName OPTIONAL, + OUT HMODULE* phModule) +{ + PUNICODE_STRING lpModuleNameW; + DWORD dwValid; + BOOL Ret = FALSE; + NTSTATUS Status; + + /* Validate parameters */ + dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, (LPCWSTR)lpModuleName, phModule); + + /* If result is invalid parameter - return failure */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE; + + /* If result is 2, there is no need to do anything - return success. */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE; + + /* Check if we don't need to convert the name */ + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) + { + /* Call the extended version of the API without conversion */ + Status = BasepGetModuleHandleExW(FALSE, + dwFlags, + (LPCWSTR)lpModuleName, + phModule); + } + else + { + /* Convert module name to unicode */ + lpModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName); + + /* Return FALSE if conversion failed */ + if (!lpModuleNameW) return FALSE; + + /* Call the extended version of the API */ + Status = BasepGetModuleHandleExW(FALSE, + dwFlags, + lpModuleNameW->Buffer, + phModule); + } + + /* If result was successful - return true */ + if (NT_SUCCESS(Status)) + Ret = TRUE; + + /* Return result */ + return Ret; +} + + +/* + * @implemented + */ +DWORD +WINAPI +LoadModule(LPCSTR lpModuleName, + LPVOID lpParameterBlock) +{ + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInformation; + LOADPARMS32 *LoadParams; + char FileName[MAX_PATH]; + LPSTR CommandLine; + DWORD Length, Error; + BOOL ProcessStatus; + ANSI_STRING AnsiStr; + UNICODE_STRING UnicStr; + RTL_PATH_TYPE PathType; + HANDLE Handle; + + LoadParams = (LOADPARMS32*)lpParameterBlock; + + /* Check load parameters */ + if (LoadParams->dwReserved || LoadParams->wMagicValue != 2) + { + /* Fail with invalid param error */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return 0; + } + + /* Search path */ + Length = SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL); + + /* Check if path was found */ + if (Length && Length < MAX_PATH) + { + /* Build StartupInfo */ + RtlZeroMemory(&StartupInfo, sizeof(StartupInfo)); + + StartupInfo.cb = sizeof(STARTUPINFOA); + StartupInfo.dwFlags = STARTF_USESHOWWINDOW; + StartupInfo.wShowWindow = LoadParams->wCmdShow; + + /* Allocate command line buffer */ + CommandLine = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + (ULONG)LoadParams->lpCmdLine[0] + Length + 2); + + /* Put module name there, then a space, and then copy provided command line, + and null-terminate it */ + RtlCopyMemory(CommandLine, FileName, Length); + CommandLine[Length] = ' '; + RtlCopyMemory(&CommandLine[Length + 1], &LoadParams->lpCmdLine[1], (ULONG)LoadParams->lpCmdLine[0]); + CommandLine[Length + 1 + (ULONG)LoadParams->lpCmdLine[0]] = 0; + + /* Create the process */ + ProcessStatus = CreateProcessA(FileName, + CommandLine, + NULL, + NULL, + FALSE, + 0, + LoadParams->lpEnvAddress, + NULL, + &StartupInfo, + &ProcessInformation); + + /* Free the command line buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine); + + if (!ProcessStatus) + { + /* Creating process failed, return right error code */ + Error = GetLastError(); + switch(Error) + { + case ERROR_BAD_EXE_FORMAT: + return ERROR_BAD_FORMAT; + + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + return Error; + } + + /* Return 0 otherwise */ + return 0; + } + + /* Wait up to 30 seconds for the process to become idle */ + if (lpfnGlobalRegisterWaitForInputIdle) + { + lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, 30000); + } + + /* Close handles */ + NtClose(ProcessInformation.hThread); + NtClose(ProcessInformation.hProcess); + + /* Return magic success value (33) */ + return 33; + } + + /* The path was not found, create an ansi string from + the module name and convert it to unicode */ + RtlInitAnsiString(&AnsiStr, lpModuleName); + if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr,&AnsiStr,TRUE))) + return ERROR_FILE_NOT_FOUND; + + /* Determine path type */ + PathType = RtlDetermineDosPathNameType_U(UnicStr.Buffer); + + /* Free the unicode module name */ + RtlFreeUnicodeString(&UnicStr); + + /* If it's a relative path, return file not found */ + if (PathType == RtlPathTypeRelative) + return ERROR_FILE_NOT_FOUND; + + /* If not, try to open it */ + Handle = CreateFile(lpModuleName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (Handle != INVALID_HANDLE_VALUE) + { + /* Opening file succeeded for some reason, close the handle and return file not found anyway */ + CloseHandle(Handle); + return ERROR_FILE_NOT_FOUND; + } + + /* Return last error which CreateFile set during an attempt to open it */ + return GetLastError(); +} + +/* + * @unimplemented + */ +FARPROC WINAPI DelayLoadFailureHook(LPCSTR pszDllName, LPCSTR pszProcName) +{ + STUB; + return NULL; +} + +/* + * @unimplemented + */ +BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL, + LPSTR lpszInitName, LPSTR lpszProcName, + FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack, + LPVOID lpBuff ) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +VOID WINAPI UTUnRegister( HMODULE hModule ) +{ + STUB; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/perfcnt.c b/dll/win32/kernel32/client/perfcnt.c new file mode 100644 index 00000000000..e25bb9d6a9d --- /dev/null +++ b/dll/win32/kernel32/client/perfcnt.c @@ -0,0 +1,62 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Win32 Base API + * FILE: dll/win32/kernel32/client/perfcnt.c + * PURPOSE: Performance Counter + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +QueryPerformanceCounter(OUT PLARGE_INTEGER lpPerformanceCount) +{ + LARGE_INTEGER Frequency; + NTSTATUS Status; + + Status = NtQueryPerformanceCounter(lpPerformanceCount, &Frequency); + if (!Frequency.QuadPart) Status = STATUS_NOT_IMPLEMENTED; + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +QueryPerformanceFrequency(OUT PLARGE_INTEGER lpFrequency) +{ + LARGE_INTEGER Count; + NTSTATUS Status; + + Status = NtQueryPerformanceCounter(&Count, lpFrequency); + if (!Count.QuadPart) Status = STATUS_NOT_IMPLEMENTED; + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/power.c b/dll/win32/kernel32/client/power.c new file mode 100644 index 00000000000..85c74e40715 --- /dev/null +++ b/dll/win32/kernel32/client/power.c @@ -0,0 +1,222 @@ +/* + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/power.c + * PURPOSE: Power Management Functions + * PROGRAMMER: Dmitry Chapyshev + * + * UPDATE HISTORY: + * 01/15/2009 Created + */ + +#include + +#define NDEBUG +#include + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +GetSystemPowerStatus(IN LPSYSTEM_POWER_STATUS PowerStatus) +{ + NTSTATUS Status; + SYSTEM_BATTERY_STATE BattState; + ULONG Max, Current; + + Status = NtPowerInformation(SystemBatteryState, + NULL, + 0, + &BattState, + sizeof(SYSTEM_BATTERY_STATE)); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + RtlZeroMemory(PowerStatus, sizeof(LPSYSTEM_POWER_STATUS)); + + PowerStatus->BatteryLifeTime = BATTERY_LIFE_UNKNOWN; + PowerStatus->BatteryFullLifeTime = BATTERY_LIFE_UNKNOWN; + PowerStatus->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN; + PowerStatus->ACLineStatus = AC_LINE_ONLINE; + + Max = BattState.MaxCapacity; + Current = BattState.RemainingCapacity; + if (Max) + { + if (Current <= Max) + { + PowerStatus->BatteryLifePercent = (100 * Current + Max / 2) / Max; + } + else + { + PowerStatus->BatteryLifePercent = 100; + } + + if (PowerStatus->BatteryLifePercent <= 32) PowerStatus->BatteryFlag |= BATTERY_FLAG_LOW; + if (PowerStatus->BatteryLifePercent >= 67) PowerStatus->BatteryFlag |= BATTERY_FLAG_HIGH; + } + + if (!BattState.BatteryPresent) PowerStatus->BatteryFlag |= BATTERY_FLAG_NO_BATTERY; + + if (BattState.Charging) PowerStatus->BatteryFlag |= BATTERY_FLAG_CHARGING; + + if (!(BattState.AcOnLine) && (BattState.BatteryPresent)) PowerStatus->ACLineStatus = AC_LINE_OFFLINE; + + if (BattState.EstimatedTime) PowerStatus->BatteryLifeTime = BattState.EstimatedTime; + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetSystemPowerState(IN BOOL fSuspend, + IN BOOL fForce) +{ + NTSTATUS Status; + + Status = NtInitiatePowerAction(PowerActionSleep, + (fSuspend != FALSE) ? + PowerSystemSleeping1 : PowerSystemHibernate, + fForce != TRUE, + FALSE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetDevicePowerState(IN HANDLE hDevice, + OUT BOOL *pfOn) +{ + DEVICE_POWER_STATE DevicePowerState; + NTSTATUS Status; + + Status = NtGetDevicePowerState(hDevice, &DevicePowerState); + if (NT_SUCCESS(Status)) + { + *pfOn = (DevicePowerState == PowerDeviceUnspecified) || + (DevicePowerState == PowerDeviceD0); + return TRUE; + } + + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +RequestDeviceWakeup(IN HANDLE hDevice) +{ + NTSTATUS Status; + + Status = NtRequestDeviceWakeup(hDevice); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +RequestWakeupLatency(IN LATENCY_TIME latency) +{ + NTSTATUS Status; + + Status = NtRequestWakeupLatency(latency); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +CancelDeviceWakeupRequest(IN HANDLE hDevice) +{ + NTSTATUS Status; + + Status = NtCancelDeviceWakeupRequest(hDevice); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +IsSystemResumeAutomatic(VOID) +{ + return (BOOL)NtIsSystemResumeAutomatic(); +} + +/* + * @implemented + */ +BOOL +WINAPI +SetMessageWaitingIndicator(IN HANDLE hMsgIndicator, + IN ULONG ulMsgCount) +{ + /* This is the correct Windows implementation */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +/* + * @implemented + */ +EXECUTION_STATE +WINAPI +SetThreadExecutionState(EXECUTION_STATE esFlags) +{ + NTSTATUS Status; + + Status = NtSetThreadExecutionState(esFlags, &esFlags); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return esFlags; +} diff --git a/dll/win32/kernel32/process/procsup.c b/dll/win32/kernel32/client/proc.c similarity index 64% rename from dll/win32/kernel32/process/procsup.c rename to dll/win32/kernel32/client/proc.c index 39f700714d3..1ba10577cec 100644 --- a/dll/win32/kernel32/process/procsup.c +++ b/dll/win32/kernel32/client/proc.c @@ -1,10 +1,12 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/process/create.c + * FILE: lib/kernel32/proc/proc.c * PURPOSE: Process functions - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * Ariadne ( ariadne@xs4all.nl) + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 */ /* INCLUDES ****************************************************************/ @@ -14,8 +16,24 @@ #define NDEBUG #include + +typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT); + +/* GLOBALS *******************************************************************/ + +static UNICODE_STRING CommandLineStringW; +static ANSI_STRING CommandLineStringA; + +static BOOL bCommandLineInitialized = FALSE; + +WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle; + +LPSTARTUPINFOA lpLocalStartupInfo = NULL; + +VOID WINAPI +RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle); + UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH"); -UNICODE_STRING BaseDefaultPath; PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry; #define CMD_STRING L"cmd /c " @@ -25,7 +43,7 @@ VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); -/* INTERNAL FUNCTIONS *******************************************************/ +/* FUNCTIONS ****************************************************************/ static LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo) @@ -872,7 +890,1281 @@ BasepInitializeEnvironment(HANDLE ProcessHandle, return STATUS_SUCCESS; } -/* FUNCTIONS ****************************************************************/ +VOID +WINAPI +InitCommandLines(VOID) +{ + PRTL_USER_PROCESS_PARAMETERS Params; + + /* get command line */ + Params = NtCurrentPeb()->ProcessParameters; + RtlNormalizeProcessParams (Params); + + /* initialize command line buffers */ + CommandLineStringW.Length = Params->CommandLine.Length; + CommandLineStringW.MaximumLength = CommandLineStringW.Length + sizeof(WCHAR); + CommandLineStringW.Buffer = RtlAllocateHeap(GetProcessHeap(), + HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, + CommandLineStringW.MaximumLength); + if (CommandLineStringW.Buffer == NULL) + { + return; + } + + RtlInitAnsiString(&CommandLineStringA, NULL); + + /* Copy command line */ + RtlCopyUnicodeString(&CommandLineStringW, + &(Params->CommandLine)); + CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString(&CommandLineStringA, + &CommandLineStringW, + TRUE); + else + RtlUnicodeStringToOemString(&CommandLineStringA, + &CommandLineStringW, + TRUE); + + CommandLineStringA.Buffer[CommandLineStringA.Length] = 0; + + bCommandLineInitialized = TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessAffinityMask(HANDLE hProcess, + PDWORD_PTR lpProcessAffinityMask, + PDWORD_PTR lpSystemAffinityMask) +{ + PROCESS_BASIC_INFORMATION ProcessInfo; + SYSTEM_BASIC_INFORMATION SystemInfo; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemBasicInformation, + &SystemInfo, + sizeof(SystemInfo), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + Status = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + (PVOID)&ProcessInfo, + sizeof(PROCESS_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask; + *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessorsAffinityMask; + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetProcessAffinityMask(HANDLE hProcess, + DWORD_PTR dwProcessAffinityMask) +{ + NTSTATUS Status; + + Status = NtSetInformationProcess(hProcess, + ProcessAffinityMask, + (PVOID)&dwProcessAffinityMask, + sizeof(DWORD)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessShutdownParameters(LPDWORD lpdwLevel, + LPDWORD lpdwFlags) +{ + CSR_API_MESSAGE CsrRequest; + ULONG Request; + NTSTATUS Status; + + Request = GET_SHUTDOWN_PARAMETERS; + Status = CsrClientCallServer(&CsrRequest, + NULL, + MAKE_CSR_API(Request, CSR_NATIVE), + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level; + *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags; + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetProcessShutdownParameters(DWORD dwLevel, + DWORD dwFlags) +{ + CSR_API_MESSAGE CsrRequest; + ULONG Request; + NTSTATUS Status; + + CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel; + CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags; + + Request = SET_SHUTDOWN_PARAMETERS; + Status = CsrClientCallServer(&CsrRequest, + NULL, + MAKE_CSR_API(Request, CSR_NATIVE), + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessWorkingSetSize(HANDLE hProcess, + PSIZE_T lpMinimumWorkingSetSize, + PSIZE_T lpMaximumWorkingSetSize) +{ + QUOTA_LIMITS QuotaLimits; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessQuotaLimits, + &QuotaLimits, + sizeof(QUOTA_LIMITS), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize; + *lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize; + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetProcessWorkingSetSize(HANDLE hProcess, + SIZE_T dwMinimumWorkingSetSize, + SIZE_T dwMaximumWorkingSetSize) +{ + QUOTA_LIMITS QuotaLimits; + NTSTATUS Status; + + QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize; + QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize; + + Status = NtSetInformationProcess(hProcess, + ProcessQuotaLimits, + &QuotaLimits, + sizeof(QUOTA_LIMITS)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessTimes(HANDLE hProcess, + LPFILETIME lpCreationTime, + LPFILETIME lpExitTime, + LPFILETIME lpKernelTime, + LPFILETIME lpUserTime) +{ + KERNEL_USER_TIMES Kut; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessTimes, + &Kut, + sizeof(Kut), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart; + lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart; + + lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart; + lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart; + + lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart; + lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart; + + lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart; + lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart; + + return TRUE; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +GetCurrentProcess(VOID) +{ + return (HANDLE)NtCurrentProcess(); +} + + +/* + * @implemented + */ +HANDLE +WINAPI +GetCurrentThread(VOID) +{ + return (HANDLE)NtCurrentThread(); +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetCurrentProcessId(VOID) +{ + return HandleToUlong(GetTeb()->ClientId.UniqueProcess); +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetExitCodeProcess(HANDLE hProcess, + LPDWORD lpExitCode) +{ + PROCESS_BASIC_INFORMATION ProcessBasic; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasic, + sizeof(PROCESS_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpExitCode = (DWORD)ProcessBasic.ExitStatus; + + return TRUE; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetProcessId(HANDLE Process) +{ + PROCESS_BASIC_INFORMATION ProcessBasic; + NTSTATUS Status; + + Status = NtQueryInformationProcess(Process, + ProcessBasicInformation, + &ProcessBasic, + sizeof(PROCESS_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return 0; + } + + return (DWORD)ProcessBasic.UniqueProcessId; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +OpenProcess(DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwProcessId) +{ + NTSTATUS errCode; + HANDLE ProcessHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; + + ClientId.UniqueProcess = UlongToHandle(dwProcessId); + ClientId.UniqueThread = 0; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + (bInheritHandle ? OBJ_INHERIT : 0), + NULL, + NULL); + + errCode = NtOpenProcess(&ProcessHandle, + dwDesiredAccess, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(errCode)) + { + BaseSetLastNTError(errCode); + return NULL; + } + + return ProcessHandle; +} + + +/* + * @implemented + */ +UINT +WINAPI +WinExec(LPCSTR lpCmdLine, + UINT uCmdShow) +{ + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInformation; + DWORD dosErr; + + RtlZeroMemory(&StartupInfo, sizeof(StartupInfo)); + StartupInfo.cb = sizeof(STARTUPINFOA); + StartupInfo.wShowWindow = (WORD)uCmdShow; + StartupInfo.dwFlags = 0; + + if (!CreateProcessA(NULL, + (PVOID)lpCmdLine, + NULL, + NULL, + FALSE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation)) + { + dosErr = GetLastError(); + return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT; + } + + if (NULL != lpfnGlobalRegisterWaitForInputIdle) + { + lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, + 10000); + } + + NtClose(ProcessInformation.hProcess); + NtClose(ProcessInformation.hThread); + + return 33; /* Something bigger than 31 means success. */ +} + + +/* + * @implemented + */ +VOID +WINAPI +RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle) +{ + lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle; + return; +} + +/* + * @implemented + */ +VOID +WINAPI +GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo) +{ + PRTL_USER_PROCESS_PARAMETERS Params; + + if (lpStartupInfo == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return; + } + + Params = NtCurrentPeb()->ProcessParameters; + + lpStartupInfo->cb = sizeof(STARTUPINFOW); + lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer; + lpStartupInfo->lpTitle = Params->WindowTitle.Buffer; + lpStartupInfo->dwX = Params->StartingX; + lpStartupInfo->dwY = Params->StartingY; + lpStartupInfo->dwXSize = Params->CountX; + lpStartupInfo->dwYSize = Params->CountY; + lpStartupInfo->dwXCountChars = Params->CountCharsX; + lpStartupInfo->dwYCountChars = Params->CountCharsY; + lpStartupInfo->dwFillAttribute = Params->FillAttribute; + lpStartupInfo->dwFlags = Params->WindowFlags; + lpStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags; + lpStartupInfo->cbReserved2 = Params->RuntimeData.Length; + lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer; + + lpStartupInfo->hStdInput = Params->StandardInput; + lpStartupInfo->hStdOutput = Params->StandardOutput; + lpStartupInfo->hStdError = Params->StandardError; +} + + +/* + * @implemented + */ +VOID +WINAPI +GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) +{ + PRTL_USER_PROCESS_PARAMETERS Params; + ANSI_STRING AnsiString; + + if (lpStartupInfo == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return; + } + + Params = NtCurrentPeb ()->ProcessParameters; + + RtlAcquirePebLock (); + + /* FIXME - not thread-safe */ + if (lpLocalStartupInfo == NULL) + { + /* create new local startup info (ansi) */ + lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(STARTUPINFOA)); + if (lpLocalStartupInfo == NULL) + { + RtlReleasePebLock(); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return; + } + + lpLocalStartupInfo->cb = sizeof(STARTUPINFOA); + + /* copy window title string */ + RtlUnicodeStringToAnsiString(&AnsiString, + &Params->WindowTitle, + TRUE); + lpLocalStartupInfo->lpTitle = AnsiString.Buffer; + + /* copy desktop info string */ + RtlUnicodeStringToAnsiString(&AnsiString, + &Params->DesktopInfo, + TRUE); + lpLocalStartupInfo->lpDesktop = AnsiString.Buffer; + + /* copy shell info string */ + RtlUnicodeStringToAnsiString(&AnsiString, + &Params->ShellInfo, + TRUE); + lpLocalStartupInfo->lpReserved = AnsiString.Buffer; + + lpLocalStartupInfo->dwX = Params->StartingX; + lpLocalStartupInfo->dwY = Params->StartingY; + lpLocalStartupInfo->dwXSize = Params->CountX; + lpLocalStartupInfo->dwYSize = Params->CountY; + lpLocalStartupInfo->dwXCountChars = Params->CountCharsX; + lpLocalStartupInfo->dwYCountChars = Params->CountCharsY; + lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute; + lpLocalStartupInfo->dwFlags = Params->WindowFlags; + lpLocalStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags; + lpLocalStartupInfo->cbReserved2 = Params->RuntimeData.Length; + lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer; + + lpLocalStartupInfo->hStdInput = Params->StandardInput; + lpLocalStartupInfo->hStdOutput = Params->StandardOutput; + lpLocalStartupInfo->hStdError = Params->StandardError; + } + + RtlReleasePebLock(); + + /* copy local startup info data to external startup info */ + memcpy(lpStartupInfo, + lpLocalStartupInfo, + sizeof(STARTUPINFOA)); +} + + +/* + * @implemented + */ +BOOL +WINAPI +FlushInstructionCache(HANDLE hProcess, + LPCVOID lpBaseAddress, + SIZE_T dwSize) +{ + NTSTATUS Status; + + Status = NtFlushInstructionCache(hProcess, + (PVOID)lpBaseAddress, + dwSize); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +VOID +WINAPI +ExitProcess(UINT uExitCode) +{ + CSR_API_MESSAGE CsrRequest; + ULONG Request; + NTSTATUS Status; + + /* kill sibling threads ... we want to be alone at this point */ + NtTerminateProcess(NULL, 0); + + /* unload all dll's */ + LdrShutdownProcess(); + + /* notify csrss of process termination */ + Request = TERMINATE_PROCESS; + Status = CsrClientCallServer(&CsrRequest, + NULL, + MAKE_CSR_API(Request, CSR_NATIVE), + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) + { + DPRINT("Failed to tell csrss about terminating process\n"); + } + + NtTerminateProcess(NtCurrentProcess (), + uExitCode); + + /* should never get here */ + ASSERT(0); + while(1); +} + + +/* + * @implemented + */ +BOOL +WINAPI +TerminateProcess(HANDLE hProcess, + UINT uExitCode) +{ + NTSTATUS Status; + + if (hProcess == NULL) + { + return FALSE; + } + + Status = NtTerminateProcess(hProcess, uExitCode); + if (NT_SUCCESS(Status)) + { + return TRUE; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @unimplemented + */ +VOID +WINAPI +FatalAppExitA(UINT uAction, + LPCSTR lpMessageText) +{ + UNICODE_STRING MessageTextU; + ANSI_STRING MessageText; + + RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText); + + RtlAnsiStringToUnicodeString(&MessageTextU, + &MessageText, + TRUE); + + FatalAppExitW(uAction, MessageTextU.Buffer); + + RtlFreeUnicodeString(&MessageTextU); +} + + +/* + * @unimplemented + */ +VOID +WINAPI +FatalAppExitW(UINT uAction, + LPCWSTR lpMessageText) +{ + static const WCHAR szUser32[] = L"user32.dll\0"; + + HMODULE hModule = GetModuleHandleW(szUser32); + MessageBoxW_Proc pMessageBoxW = NULL; + + DPRINT1("AppExit\n"); + + if (hModule) + pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule, "MessageBoxW"); + + if (pMessageBoxW) + pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK); + else + DPRINT1("%s\n", lpMessageText); + + ExitProcess(0); +} + + +/* + * @implemented + */ +VOID +WINAPI +FatalExit(int ExitCode) +{ + ExitProcess(ExitCode); +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetPriorityClass(HANDLE hProcess) +{ + NTSTATUS Status; + PROCESS_PRIORITY_CLASS PriorityClass; + + Status = NtQueryInformationProcess(hProcess, + ProcessPriorityClass, + &PriorityClass, + sizeof(PROCESS_PRIORITY_CLASS), + NULL); + if(NT_SUCCESS(Status)) + { + switch(PriorityClass.PriorityClass) + { + case PROCESS_PRIORITY_CLASS_IDLE: + return IDLE_PRIORITY_CLASS; + + case PROCESS_PRIORITY_CLASS_BELOW_NORMAL: + return BELOW_NORMAL_PRIORITY_CLASS; + + case PROCESS_PRIORITY_CLASS_NORMAL: + return NORMAL_PRIORITY_CLASS; + + case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL: + return ABOVE_NORMAL_PRIORITY_CLASS; + + case PROCESS_PRIORITY_CLASS_HIGH: + return HIGH_PRIORITY_CLASS; + + case PROCESS_PRIORITY_CLASS_REALTIME: + return REALTIME_PRIORITY_CLASS; + + default: + return NORMAL_PRIORITY_CLASS; + } + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetPriorityClass(HANDLE hProcess, + DWORD dwPriorityClass) +{ + NTSTATUS Status; + PROCESS_PRIORITY_CLASS PriorityClass; + + switch (dwPriorityClass) + { + case IDLE_PRIORITY_CLASS: + PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; + break; + + case BELOW_NORMAL_PRIORITY_CLASS: + PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; + break; + + case NORMAL_PRIORITY_CLASS: + PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; + break; + + case ABOVE_NORMAL_PRIORITY_CLASS: + PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; + break; + + case HIGH_PRIORITY_CLASS: + PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; + break; + + case REALTIME_PRIORITY_CLASS: + PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME; + break; + + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + PriorityClass.Foreground = FALSE; + + Status = NtSetInformationProcess(hProcess, + ProcessPriorityClass, + &PriorityClass, + sizeof(PROCESS_PRIORITY_CLASS)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetProcessVersion(DWORD ProcessId) +{ + DWORD Version = 0; + PIMAGE_NT_HEADERS NtHeader = NULL; + IMAGE_NT_HEADERS NtHeaders; + IMAGE_DOS_HEADER DosHeader; + PROCESS_BASIC_INFORMATION ProcessBasicInfo; + PVOID BaseAddress = NULL; + HANDLE ProcessHandle = NULL; + NTSTATUS Status; + SIZE_T Count; + PEB Peb; + + _SEH2_TRY + { + if (0 == ProcessId || GetCurrentProcessId() == ProcessId) + { + /* Caller's */ + BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress; + NtHeader = RtlImageNtHeader(BaseAddress); + + Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) | + (NtHeader->OptionalHeader.MinorOperatingSystemVersion); + } + else + { + /* Other process */ + ProcessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, + FALSE, + ProcessId); + + if (!ProcessHandle) return 0; + + Status = NtQueryInformationProcess(ProcessHandle, + ProcessBasicInformation, + &ProcessBasicInfo, + sizeof(ProcessBasicInfo), + NULL); + + if (!NT_SUCCESS(Status)) goto Error; + + Status = NtReadVirtualMemory(ProcessHandle, + ProcessBasicInfo.PebBaseAddress, + &Peb, + sizeof(Peb), + &Count); + + if (!NT_SUCCESS(Status) || Count != sizeof(Peb)) goto Error; + + memset(&DosHeader, 0, sizeof(DosHeader)); + Status = NtReadVirtualMemory(ProcessHandle, + Peb.ImageBaseAddress, + &DosHeader, + sizeof(DosHeader), + &Count); + + if (!NT_SUCCESS(Status) || Count != sizeof(DosHeader)) goto Error; + if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) goto Error; + + memset(&NtHeaders, 0, sizeof(NtHeaders)); + Status = NtReadVirtualMemory(ProcessHandle, + (char *)Peb.ImageBaseAddress + DosHeader.e_lfanew, + &NtHeaders, + sizeof(NtHeaders), + &Count); + + if (!NT_SUCCESS(Status) || Count != sizeof(NtHeaders)) goto Error; + if (NtHeaders.Signature != IMAGE_NT_SIGNATURE) goto Error; + + Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion, + NtHeaders.OptionalHeader.MajorSubsystemVersion); + +Error: + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + } + } + } + _SEH2_FINALLY + { + if (ProcessHandle) CloseHandle(ProcessHandle); + } + _SEH2_END; + + return Version; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessIoCounters(HANDLE hProcess, + PIO_COUNTERS lpIoCounters) +{ + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessIoCounters, + lpIoCounters, + sizeof(IO_COUNTERS), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessPriorityBoost(HANDLE hProcess, + PBOOL pDisablePriorityBoost) +{ + NTSTATUS Status; + ULONG PriorityBoost; + + Status = NtQueryInformationProcess(hProcess, + ProcessPriorityBoost, + &PriorityBoost, + sizeof(ULONG), + NULL); + if (NT_SUCCESS(Status)) + { + *pDisablePriorityBoost = PriorityBoost; + return TRUE; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetProcessPriorityBoost(HANDLE hProcess, + BOOL bDisablePriorityBoost) +{ + NTSTATUS Status; + ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */ + + Status = NtSetInformationProcess(hProcess, + ProcessPriorityBoost, + &PriorityBoost, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetProcessHandleCount(HANDLE hProcess, + PDWORD pdwHandleCount) +{ + ULONG phc; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessHandleCount, + &phc, + sizeof(ULONG), + NULL); + if(NT_SUCCESS(Status)) + { + *pdwHandleCount = phc; + return TRUE; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +IsWow64Process(HANDLE hProcess, + PBOOL Wow64Process) +{ + ULONG_PTR pbi; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessWow64Information, + &pbi, + sizeof(pbi), + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + *Wow64Process = (pbi != 0); + + return TRUE; +} + +/* + * @implemented + */ +LPSTR +WINAPI +GetCommandLineA(VOID) +{ + DPRINT("CommandLine \'%s\'\n", CommandLineStringA.Buffer); + return CommandLineStringA.Buffer; +} + + +/* + * @implemented + */ +LPWSTR +WINAPI +GetCommandLineW(VOID) +{ + DPRINT("CommandLine \'%S\'\n", CommandLineStringW.Buffer); + return CommandLineStringW.Buffer; +} + +/* + * @implemented + */ +BOOL +NTAPI +ReadProcessMemory(IN HANDLE hProcess, + IN LPCVOID lpBaseAddress, + IN LPVOID lpBuffer, + IN SIZE_T nSize, + OUT SIZE_T* lpNumberOfBytesRead) +{ + NTSTATUS Status; + + /* Do the read */ + Status = NtReadVirtualMemory(hProcess, + (PVOID)lpBaseAddress, + lpBuffer, + nSize, + lpNumberOfBytesRead); + if (!NT_SUCCESS(Status)) + { + /* We failed */ + BaseSetLastNTError (Status); + return FALSE; + } + + /* Return success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +NTAPI +WriteProcessMemory(IN HANDLE hProcess, + IN LPVOID lpBaseAddress, + IN LPCVOID lpBuffer, + IN SIZE_T nSize, + OUT SIZE_T *lpNumberOfBytesWritten) +{ + NTSTATUS Status; + ULONG OldValue; + SIZE_T RegionSize; + PVOID Base; + BOOLEAN UnProtect; + + /* Set parameters for protect call */ + RegionSize = nSize; + Base = lpBaseAddress; + + /* Check the current status */ + Status = NtProtectVirtualMemory(hProcess, + &Base, + &RegionSize, + PAGE_EXECUTE_READWRITE, + &OldValue); + if (NT_SUCCESS(Status)) + { + /* Check if we are unprotecting */ + UnProtect = OldValue & (PAGE_READWRITE | + PAGE_WRITECOPY | + PAGE_EXECUTE_READWRITE | + PAGE_EXECUTE_WRITECOPY) ? FALSE : TRUE; + if (!UnProtect) + { + /* Set the new protection */ + Status = NtProtectVirtualMemory(hProcess, + &Base, + &RegionSize, + OldValue, + &OldValue); + + /* Write the memory */ + Status = NtWriteVirtualMemory(hProcess, + lpBaseAddress, + (LPVOID)lpBuffer, + nSize, + lpNumberOfBytesWritten); + if (!NT_SUCCESS(Status)) + { + /* We failed */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Flush the ITLB */ + NtFlushInstructionCache(hProcess, lpBaseAddress, nSize); + return TRUE; + } + else + { + /* Check if we were read only */ + if ((OldValue & PAGE_NOACCESS) || (OldValue & PAGE_READONLY)) + { + /* Restore protection and fail */ + NtProtectVirtualMemory(hProcess, + &Base, + &RegionSize, + OldValue, + &OldValue); + BaseSetLastNTError(STATUS_ACCESS_VIOLATION); + return FALSE; + } + + /* Otherwise, do the write */ + Status = NtWriteVirtualMemory(hProcess, + lpBaseAddress, + (LPVOID)lpBuffer, + nSize, + lpNumberOfBytesWritten); + + /* And restore the protection */ + NtProtectVirtualMemory(hProcess, + &Base, + &RegionSize, + OldValue, + &OldValue); + if (!NT_SUCCESS(Status)) + { + /* We failed */ + BaseSetLastNTError(STATUS_ACCESS_VIOLATION); + return FALSE; + } + + /* Flush the ITLB */ + NtFlushInstructionCache(hProcess, lpBaseAddress, nSize); + return TRUE; + } + } + else + { + /* We failed */ + BaseSetLastNTError(Status); + return FALSE; + } +} + +/* + * @implemented + */ +BOOL +WINAPI +ProcessIdToSessionId(IN DWORD dwProcessId, + OUT DWORD *pSessionId) +{ + PROCESS_SESSION_INFORMATION SessionInformation; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; + HANDLE ProcessHandle; + NTSTATUS Status; + + if (IsBadWritePtr(pSessionId, sizeof(DWORD))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ClientId.UniqueProcess = UlongToHandle(dwProcessId); + ClientId.UniqueThread = 0; + + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + + Status = NtOpenProcess(&ProcessHandle, + PROCESS_QUERY_INFORMATION, + &ObjectAttributes, + &ClientId); + if (NT_SUCCESS(Status)) + { + Status = NtQueryInformationProcess(ProcessHandle, + ProcessSessionInformation, + &SessionInformation, + sizeof(SessionInformation), + NULL); + NtClose(ProcessHandle); + + if (NT_SUCCESS(Status)) + { + *pSessionId = SessionInformation.SessionId; + return TRUE; + } + } + + BaseSetLastNTError(Status); + return FALSE; +} + +BOOL +WINAPI +SetProcessWorkingSetSizeEx(IN HANDLE hProcess, + IN SIZE_T dwMinimumWorkingSetSize, + IN SIZE_T dwMaximumWorkingSetSize, + IN DWORD Flags) +{ + STUB; + return FALSE; +} + + +BOOL +WINAPI +GetProcessWorkingSetSizeEx(IN HANDLE hProcess, + OUT PSIZE_T lpMinimumWorkingSetSize, + OUT PSIZE_T lpMaximumWorkingSetSize, + OUT PDWORD Flags) +{ + STUB; + return FALSE; +} /* * @implemented @@ -1167,13 +2459,13 @@ GetAppName: { /* Fake the error */ CloseHandle(hFile); - SetLastErrorByStatus(STATUS_OBJECT_NAME_NOT_FOUND); + BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND); } } else { /* Immediately set the error */ - SetLastErrorByStatus(STATUS_OBJECT_NAME_NOT_FOUND); + BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND); } /* Did we already fail once? */ @@ -1332,7 +2624,7 @@ GetAppName: case STATUS_OBJECT_NAME_NOT_FOUND: case STATUS_OBJECT_PATH_NOT_FOUND: - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; default: @@ -1361,7 +2653,7 @@ GetAppName: if(!NT_SUCCESS(Status)) { DPRINT1("Unable to get SectionImageInformation, status 0x%x\n", Status); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; } @@ -1412,7 +2704,7 @@ GetAppName: if (!NT_SUCCESS(Status)) { DPRINT1("Failed to connect to DbgUI!\n"); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; } @@ -1438,7 +2730,7 @@ GetAppName: if (!NT_SUCCESS(Status)) { DPRINT1("Unable to create process, status 0x%x\n", Status); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; } @@ -1452,7 +2744,7 @@ GetAppName: if(!NT_SUCCESS(Status)) { DPRINT1("Unable to set new process priority, status 0x%x\n", Status); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; } } @@ -1595,7 +2887,7 @@ GetAppName: if (!NT_SUCCESS(Status)) { DPRINT1("Could not initialize Process Environment\n"); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; } @@ -1641,7 +2933,7 @@ GetAppName: if (!NT_SUCCESS(Status)) { DPRINT1("CSR Notification Failed"); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); goto Cleanup; } diff --git a/dll/win32/kernel32/client/resntfy.c b/dll/win32/kernel32/client/resntfy.c new file mode 100644 index 00000000000..ac78a1ec0ca --- /dev/null +++ b/dll/win32/kernel32/client/resntfy.c @@ -0,0 +1,95 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Win32 Base API + * FILE: dll/win32/kernel32/client/resnotify.c + * PURPOSE: Memory Resource Notifications + * PROGRAMMER: Thomas Weidenmueller + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +/* + * @implemented + */ +HANDLE +WINAPI +CreateMemoryResourceNotification(IN MEMORY_RESOURCE_NOTIFICATION_TYPE NotificationType) +{ + UNICODE_STRING EventName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hEvent; + NTSTATUS Status; + + if (NotificationType > HighMemoryResourceNotification) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + RtlInitUnicodeString(&EventName, + NotificationType ? + L"\\KernelObjects\\HighMemoryCondition" : + L"\\KernelObjects\\LowMemoryCondition"); + + InitializeObjectAttributes(&ObjectAttributes, + &EventName, + 0, + hBaseDir, + NULL); + + Status = NtOpenEvent(&hEvent, + EVENT_QUERY_STATE | SYNCHRONIZE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + return hEvent; +} + +/* + * @implemented + */ +BOOL +WINAPI +QueryMemoryResourceNotification(IN HANDLE ResourceNotificationHandle, + OUT PBOOL ResourceState) +{ + EVENT_BASIC_INFORMATION EventInfo; + NTSTATUS Status; + + if ((ResourceNotificationHandle) && + (ResourceNotificationHandle != INVALID_HANDLE_VALUE) && + (ResourceState)) + { + Status = NtQueryEvent(ResourceNotificationHandle, + EventBasicInformation, + &EventInfo, + sizeof(EventInfo), + NULL); + if (NT_SUCCESS(Status)) + { + *ResourceState = (EventInfo.EventState == 1); + return TRUE; + } + + BaseSetLastNTError(Status); + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + } + + return FALSE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/session.c b/dll/win32/kernel32/client/session.c new file mode 100644 index 00000000000..496c05e3a1d --- /dev/null +++ b/dll/win32/kernel32/client/session.c @@ -0,0 +1,54 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/kernel32/client/session.c + * PURPOSE: Session Support APIs + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +/* + * @unimplemented + */ +DWORD +WINAPI +DosPathToSessionPathW(IN DWORD SessionID, + IN LPWSTR InPath, + OUT LPWSTR *OutPath) +{ + UNIMPLEMENTED; + return 0; +} + +/* + * @unimplemented + */ +DWORD +WINAPI +DosPathToSessionPathA(IN DWORD SessionId, + IN LPSTR InPath, + OUT LPSTR *OutPath) +{ + UNIMPLEMENTED; + return 0; +} + +/* + * @implemented + */ +DWORD +WINAPI +WTSGetActiveConsoleSessionId(VOID) +{ + return SharedUserData->ActiveConsoleId; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/synch.c b/dll/win32/kernel32/client/synch.c new file mode 100644 index 00000000000..83e82a448b1 --- /dev/null +++ b/dll/win32/kernel32/client/synch.c @@ -0,0 +1,859 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/kernel32/synch/wait.c + * PURPOSE: Wrappers for the NT Wait Implementation + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +DWORD +WINAPI +WaitForSingleObject(IN HANDLE hHandle, + IN DWORD dwMilliseconds) +{ + /* Call the extended API */ + return WaitForSingleObjectEx(hHandle, dwMilliseconds, FALSE); +} + +/* + * @implemented + */ +DWORD +WINAPI +WaitForSingleObjectEx(IN HANDLE hHandle, + IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + PLARGE_INTEGER TimePtr; + LARGE_INTEGER Time; + NTSTATUS Status; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; + + /* APCs must execute with the default activation context */ + if (bAlertable) + { + /* Setup the frame */ + RtlZeroMemory(&ActCtx, sizeof(ActCtx)); + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); + } + + /* Get real handle */ + hHandle = TranslateStdHandle(hHandle); + + /* Check for console handle */ + if ((IsConsoleHandle(hHandle)) && (VerifyConsoleIoHandle(hHandle))) + { + /* Get the real wait handle */ + hHandle = GetConsoleInputWaitHandle(); + } + + /* Convert the timeout */ + TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); + + /* Start wait loop */ + do + { + /* Do the wait */ + Status = NtWaitForSingleObject(hHandle, (BOOLEAN)bAlertable, TimePtr); + if (!NT_SUCCESS(Status)) + { + /* The wait failed */ + BaseSetLastNTError(Status); + Status = WAIT_FAILED; + } + } while ((Status == STATUS_ALERTED) && (bAlertable)); + + /* Cleanup the activation context */ + if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); + + /* Return wait status */ + return Status; +} + +/* + * @implemented + */ +DWORD +WINAPI +WaitForMultipleObjects(IN DWORD nCount, + IN CONST HANDLE *lpHandles, + IN BOOL bWaitAll, + IN DWORD dwMilliseconds) +{ + /* Call the extended API */ + return WaitForMultipleObjectsEx(nCount, + lpHandles, + bWaitAll, + dwMilliseconds, + FALSE); +} + +/* + * @implemented + */ +DWORD +WINAPI +WaitForMultipleObjectsEx(IN DWORD nCount, + IN CONST HANDLE *lpHandles, + IN BOOL bWaitAll, + IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + PLARGE_INTEGER TimePtr; + LARGE_INTEGER Time; + PHANDLE HandleBuffer; + HANDLE Handle[8]; + DWORD i; + NTSTATUS Status; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; + + /* APCs must execute with the default activation context */ + if (bAlertable) + { + /* Setup the frame */ + RtlZeroMemory(&ActCtx, sizeof(ActCtx)); + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); + } + + /* Check if we have more handles then we locally optimize */ + if (nCount > 8) + { + /* Allocate a buffer for them */ + HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + nCount * sizeof(HANDLE)); + if (!HandleBuffer) + { + /* No buffer, fail the wait */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); + return WAIT_FAILED; + } + } + else + { + /* Otherwise, use our local buffer */ + HandleBuffer = Handle; + } + + /* Copy the handles into our buffer and loop them all */ + RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE)); + for (i = 0; i < nCount; i++) + { + /* Check what kind of handle this is */ + HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]); + + /* Check for console handle */ + if ((IsConsoleHandle(HandleBuffer[i])) && + (VerifyConsoleIoHandle(HandleBuffer[i]))) + { + /* Get the real wait handle */ + HandleBuffer[i] = GetConsoleInputWaitHandle(); + } + } + + /* Convert the timeout */ + TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); + + /* Start wait loop */ + do + { + /* Do the wait */ + Status = NtWaitForMultipleObjects(nCount, + HandleBuffer, + bWaitAll ? WaitAll : WaitAny, + (BOOLEAN)bAlertable, + TimePtr); + if (!NT_SUCCESS(Status)) + { + /* Wait failed */ + BaseSetLastNTError(Status); + Status = WAIT_FAILED; + } + } while ((Status == STATUS_ALERTED) && (bAlertable)); + + /* Check if we didn't use our local buffer */ + if (HandleBuffer != Handle) + { + /* Free the allocated one */ + RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); + } + + /* Cleanup the activation context */ + if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); + + /* Return wait status */ + return Status; +} + +/* + * @implemented + */ +DWORD +WINAPI +SignalObjectAndWait(IN HANDLE hObjectToSignal, + IN HANDLE hObjectToWaitOn, + IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + PLARGE_INTEGER TimePtr; + LARGE_INTEGER Time; + NTSTATUS Status; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; + + /* APCs must execute with the default activation context */ + if (bAlertable) + { + /* Setup the frame */ + RtlZeroMemory(&ActCtx, sizeof(ActCtx)); + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); + } + + /* Get real handle */ + hObjectToWaitOn = TranslateStdHandle(hObjectToWaitOn); + + /* Check for console handle */ + if ((IsConsoleHandle(hObjectToWaitOn)) && + (VerifyConsoleIoHandle(hObjectToWaitOn))) + { + /* Get the real wait handle */ + hObjectToWaitOn = GetConsoleInputWaitHandle(); + } + + /* Convert the timeout */ + TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); + + /* Start wait loop */ + do + { + /* Do the wait */ + Status = NtSignalAndWaitForSingleObject(hObjectToSignal, + hObjectToWaitOn, + (BOOLEAN)bAlertable, + TimePtr); + if (!NT_SUCCESS(Status)) + { + /* The wait failed */ + BaseSetLastNTError(Status); + Status = WAIT_FAILED; + } + } while ((Status == STATUS_ALERTED) && (bAlertable)); + + /* Cleanup the activation context */ + if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); + + /* Return wait status */ + return Status; +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateWaitableTimerW(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, + IN BOOL bManualReset, + IN LPCWSTR lpTimerName OPTIONAL) +{ + CreateNtObjectFromWin32Api(WaitableTimer, Timer, TIMER, + lpTimerAttributes, + lpTimerName, + bManualReset ? NotificationTimer : SynchronizationTimer); +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateWaitableTimerA(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, + IN BOOL bManualReset, + IN LPCSTR lpTimerName OPTIONAL) +{ + ConvertWin32AnsiObjectApiToUnicodeApi(WaitableTimer, lpTimerName, lpTimerAttributes, bManualReset); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenWaitableTimerW(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpTimerName) +{ + OpenNtObjectFromWin32Api(Timer, dwDesiredAccess, bInheritHandle, lpTimerName); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenWaitableTimerA(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpTimerName) +{ + ConvertOpenWin32AnsiObjectApiToUnicodeApi(WaitableTimer, dwDesiredAccess, bInheritHandle, lpTimerName); +} + +/* + * @implemented + */ +BOOL +WINAPI +SetWaitableTimer(IN HANDLE hTimer, + IN const LARGE_INTEGER *pDueTime, + IN LONG lPeriod, + IN PTIMERAPCROUTINE pfnCompletionRoutine OPTIONAL, + IN OPTIONAL LPVOID lpArgToCompletionRoutine, + IN BOOL fResume) +{ + NTSTATUS Status; + + /* Set the timer */ + Status = NtSetTimer(hTimer, + (PLARGE_INTEGER)pDueTime, + (PTIMER_APC_ROUTINE)pfnCompletionRoutine, + lpArgToCompletionRoutine, + (BOOLEAN)fResume, + lPeriod, + NULL); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +CancelWaitableTimer(IN HANDLE hTimer) +{ + NTSTATUS Status; + + /* Cancel the timer */ + Status = NtCancelTimer(hTimer, NULL); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateSemaphoreA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCSTR lpName OPTIONAL) +{ + ConvertWin32AnsiObjectApiToUnicodeApi(Semaphore, lpName, lpSemaphoreAttributes, lInitialCount, lMaximumCount); +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateSemaphoreW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCWSTR lpName OPTIONAL) +{ + CreateNtObjectFromWin32Api(Semaphore, Semaphore, SEMAPHORE, + lpSemaphoreAttributes, + lpName, + lInitialCount, + lMaximumCount); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenSemaphoreA(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName) +{ + ConvertOpenWin32AnsiObjectApiToUnicodeApi(Semaphore, dwDesiredAccess, bInheritHandle, lpName); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenSemaphoreW(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + OpenNtObjectFromWin32Api(Semaphore, dwDesiredAccess, bInheritHandle, lpName); +} + +/* + * @implemented + */ +BOOL +WINAPI +ReleaseSemaphore(IN HANDLE hSemaphore, + IN LONG lReleaseCount, + IN LPLONG lpPreviousCount) +{ + NTSTATUS Status; + + /* Release the semaphore */ + Status = NtReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, + IN BOOL bInitialOwner, + IN LPCSTR lpName OPTIONAL) +{ + ConvertWin32AnsiObjectApiToUnicodeApi(Mutex, lpName, lpMutexAttributes, bInitialOwner); +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, + IN BOOL bInitialOwner, + IN LPCWSTR lpName OPTIONAL) +{ + CreateNtObjectFromWin32Api(Mutex, Mutant, MUTEX, + lpMutexAttributes, + lpName, + bInitialOwner); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenMutexA(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName) +{ + ConvertOpenWin32AnsiObjectApiToUnicodeApi(Mutex, dwDesiredAccess, bInheritHandle, lpName); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenMutexW(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + OpenNtObjectFromWin32Api(Mutant, dwDesiredAccess, bInheritHandle, lpName); +} + +/* + * @implemented + */ +BOOL +WINAPI +ReleaseMutex(IN HANDLE hMutex) +{ + NTSTATUS Status; + + /* Release the mutant */ + Status = NtReleaseMutant(hMutex, NULL); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, + IN BOOL bManualReset, + IN BOOL bInitialState, + IN LPCSTR lpName OPTIONAL) +{ + ConvertWin32AnsiObjectApiToUnicodeApi(Event, lpName, lpEventAttributes, bManualReset, bInitialState); +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, + IN BOOL bManualReset, + IN BOOL bInitialState, + IN LPCWSTR lpName OPTIONAL) +{ + CreateNtObjectFromWin32Api(Event, Event, EVENT, + lpEventAttributes, + lpName, + bManualReset ? NotificationTimer : SynchronizationTimer, + bInitialState); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenEventA(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName) +{ + ConvertOpenWin32AnsiObjectApiToUnicodeApi(Event, dwDesiredAccess, bInheritHandle, lpName); +} + +/* + * @implemented + */ +HANDLE +WINAPI +OpenEventW(IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName) +{ + OpenNtObjectFromWin32Api(Event, dwDesiredAccess, bInheritHandle, lpName); +} + +/* + * @implemented + */ +BOOL +WINAPI +PulseEvent(IN HANDLE hEvent) +{ + NTSTATUS Status; + + /* Pulse the event */ + Status = NtPulseEvent(hEvent, NULL); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +ResetEvent(IN HANDLE hEvent) +{ + NTSTATUS Status; + + /* Clear the event */ + Status = NtResetEvent(hEvent, NULL); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetEvent(IN HANDLE hEvent) +{ + NTSTATUS Status; + + /* Set the event */ + Status = NtSetEvent(hEvent, NULL); + if (NT_SUCCESS(Status)) return TRUE; + + /* If we got here, then we failed */ + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +VOID +WINAPI +InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection) +{ + NTSTATUS Status; + + /* Initialize the critical section and raise an exception if we failed */ + Status = RtlInitializeCriticalSection((PVOID)lpCriticalSection); + if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status); +} + +/* + * @implemented + */ +BOOL +WINAPI +InitializeCriticalSectionAndSpinCount(OUT LPCRITICAL_SECTION lpCriticalSection, + IN DWORD dwSpinCount) +{ + NTSTATUS Status; + + /* Initialize the critical section */ + Status = RtlInitializeCriticalSectionAndSpinCount((PVOID)lpCriticalSection, + dwSpinCount); + if (!NT_SUCCESS(Status)) + { + /* Set failure code */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} + +/* + * @implemented + */ +VOID +WINAPI +Sleep(IN DWORD dwMilliseconds) +{ + /* Call the new API */ + SleepEx(dwMilliseconds, FALSE); +} + + +/* + * @implemented + */ +DWORD +WINAPI +SleepEx(IN DWORD dwMilliseconds, + IN BOOL bAlertable) +{ + LARGE_INTEGER Time; + PLARGE_INTEGER TimePtr; + NTSTATUS errCode; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; + + /* APCs must execute with the default activation context */ + if (bAlertable) + { + /* Setup the frame */ + RtlZeroMemory(&ActCtx, sizeof(ActCtx)); + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); + } + + /* Convert the timeout */ + TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); + if (!TimePtr) + { + /* Turn an infinite wait into a really long wait */ + Time.LowPart = 0; + Time.HighPart = 0x80000000; + TimePtr = &Time; + } + + /* Loop the delay while APCs are alerting us */ + do + { + /* Do the delay */ + errCode = NtDelayExecution((BOOLEAN)bAlertable, TimePtr); + } + while ((bAlertable) && (errCode == STATUS_ALERTED)); + + /* Cleanup the activation context */ + if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); + + /* Return the correct code */ + return (errCode == STATUS_USER_APC) ? WAIT_IO_COMPLETION : 0; +} + +/* + * @implemented + */ +BOOL +WINAPI +RegisterWaitForSingleObject(OUT PHANDLE phNewWaitObject, + IN HANDLE hObject, + IN WAITORTIMERCALLBACK Callback, + IN PVOID Context, + IN ULONG dwMilliseconds, + IN ULONG dwFlags) +{ + NTSTATUS Status; + + /* Get real handle */ + hObject = TranslateStdHandle(hObject); + + /* Check for console handle */ + if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) + { + /* Get the real wait handle */ + hObject = GetConsoleInputWaitHandle(); + } + + /* Register the wait now */ + Status = RtlRegisterWait(phNewWaitObject, + hObject, + Callback, + Context, + dwMilliseconds, + dwFlags); + if (!NT_SUCCESS(Status)) + { + /* Return failure */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* All good */ + return TRUE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +RegisterWaitForSingleObjectEx(IN HANDLE hObject, + IN WAITORTIMERCALLBACK Callback, + IN PVOID Context, + IN ULONG dwMilliseconds, + IN ULONG dwFlags) +{ + NTSTATUS Status; + HANDLE hNewWaitObject; + + /* Get real handle */ + hObject = TranslateStdHandle(hObject); + + /* Check for console handle */ + if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) + { + /* Get the real wait handle */ + hObject = GetConsoleInputWaitHandle(); + } + + /* Register the wait */ + Status = RtlRegisterWait(&hNewWaitObject, + hObject, + Callback, + Context, + dwMilliseconds, + dwFlags); + if (!NT_SUCCESS(Status)) + { + /* Return failure */ + BaseSetLastNTError(Status); + return NULL; + } + + /* Return the object */ + return hNewWaitObject; +} + +/* + * @implemented + */ +BOOL +WINAPI +UnregisterWait(IN HANDLE WaitHandle) +{ + NTSTATUS Status; + + /* Check for invalid handle */ + if (!WaitHandle) + { + /* Fail */ + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + /* Deregister the wait and check status */ + Status = RtlDeregisterWaitEx(WaitHandle, NULL); + if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING)) + { + /* Failure or non-blocking call */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* All good */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +UnregisterWaitEx(IN HANDLE WaitHandle, + IN HANDLE CompletionEvent) +{ + NTSTATUS Status; + + /* Check for invalid handle */ + if (!WaitHandle) + { + /* Fail */ + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + /* Deregister the wait and check status */ + Status = RtlDeregisterWaitEx(WaitHandle, CompletionEvent); + if (!(NT_SUCCESS(Status)) || + ((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING))) + { + /* Failure or non-blocking call */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* All good */ + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/sysinfo.c b/dll/win32/kernel32/client/sysinfo.c new file mode 100644 index 00000000000..580f63b10c7 --- /dev/null +++ b/dll/win32/kernel32/client/sysinfo.c @@ -0,0 +1,367 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: See COPYING in the top level directory + * FILE: dll/win32/kernel32/client/sysinfo.c + * PURPOSE: System Information Functions + * PROGRAMMERS: Emanuele Aliberti + * Christoph von Wittich + * Thomas Weidenmueller + * Gunnar Andre Dalsnes + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +#define PV_NT351 0x00030033 + +/* PRIVATE FUNCTIONS **********************************************************/ + +VOID +WINAPI +GetSystemInfoInternal(IN PSYSTEM_BASIC_INFORMATION BasicInfo, + IN PSYSTEM_PROCESSOR_INFORMATION ProcInfo, + OUT LPSYSTEM_INFO SystemInfo) +{ + RtlZeroMemory(SystemInfo, sizeof (SYSTEM_INFO)); + SystemInfo->wProcessorArchitecture = ProcInfo->ProcessorArchitecture; + SystemInfo->wReserved = 0; + SystemInfo->dwPageSize = BasicInfo->PageSize; + SystemInfo->lpMinimumApplicationAddress = (PVOID)BasicInfo->MinimumUserModeAddress; + SystemInfo->lpMaximumApplicationAddress = (PVOID)BasicInfo->MaximumUserModeAddress; + SystemInfo->dwActiveProcessorMask = BasicInfo->ActiveProcessorsAffinityMask; + SystemInfo->dwNumberOfProcessors = BasicInfo->NumberOfProcessors; + SystemInfo->wProcessorLevel = ProcInfo->ProcessorLevel; + SystemInfo->wProcessorRevision = ProcInfo->ProcessorRevision; + SystemInfo->dwAllocationGranularity = BasicInfo->AllocationGranularity; + + switch (ProcInfo->ProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + switch (ProcInfo->ProcessorLevel) + { + case 3: + SystemInfo->dwProcessorType = PROCESSOR_INTEL_386; + break; + case 4: + SystemInfo->dwProcessorType = PROCESSOR_INTEL_486; + break; + default: + SystemInfo->dwProcessorType = PROCESSOR_INTEL_PENTIUM; + } + break; + + case PROCESSOR_ARCHITECTURE_AMD64: + SystemInfo->dwProcessorType = PROCESSOR_AMD_X8664; + break; + + case PROCESSOR_ARCHITECTURE_IA64: + SystemInfo->dwProcessorType = PROCESSOR_INTEL_IA64; + break; + + default: + SystemInfo->dwProcessorType = 0; + break; + } + + if (PV_NT351 > GetProcessVersion(0)) + { + SystemInfo->wProcessorLevel = 0; + SystemInfo->wProcessorRevision = 0; + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +SIZE_T +WINAPI +GetLargePageMinimum(VOID) +{ + return SharedUserData->LargePageMinimum; +} + +/* + * @implemented + */ +VOID +WINAPI +GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo) +{ + SYSTEM_BASIC_INFORMATION BasicInfo; + SYSTEM_PROCESSOR_INFORMATION ProcInfo; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemBasicInformation, + &BasicInfo, + sizeof(BasicInfo), + 0); + if (!NT_SUCCESS(Status)) return; + + Status = NtQuerySystemInformation(SystemProcessorInformation, + &ProcInfo, + sizeof(ProcInfo), + 0); + if (!NT_SUCCESS(Status)) return; + + GetSystemInfoInternal(&BasicInfo, &ProcInfo, lpSystemInfo); +} + +/* + * @implemented + */ +BOOL +WINAPI +IsProcessorFeaturePresent(IN DWORD ProcessorFeature) +{ + if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return FALSE; + return ((BOOL)SharedUserData->ProcessorFeatures[ProcessorFeature]); +} + +/* + * @implemented + */ +BOOL +WINAPI +GetSystemRegistryQuota(OUT PDWORD pdwQuotaAllowed, + OUT PDWORD pdwQuotaUsed) +{ + SYSTEM_REGISTRY_QUOTA_INFORMATION QuotaInfo; + ULONG BytesWritten; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemRegistryQuotaInformation, + &QuotaInfo, + sizeof(QuotaInfo), + &BytesWritten); + if (NT_SUCCESS(Status)) + { + if (pdwQuotaAllowed) *pdwQuotaAllowed = QuotaInfo.RegistryQuotaAllowed; + if (pdwQuotaUsed) *pdwQuotaUsed = QuotaInfo.RegistryQuotaUsed; + return TRUE; + } + + BaseSetLastNTError(Status); + return FALSE; +} + +/* + * @implemented + */ +VOID +WINAPI +GetNativeSystemInfo(IN LPSYSTEM_INFO lpSystemInfo) +{ + SYSTEM_BASIC_INFORMATION BasicInfo; + SYSTEM_PROCESSOR_INFORMATION ProcInfo; + NTSTATUS Status; + + /* FIXME: Should be SystemNativeBasicInformation */ + Status = NtQuerySystemInformation(SystemBasicInformation, + &BasicInfo, + sizeof(BasicInfo), + 0); + if (!NT_SUCCESS(Status)) return; + + /* FIXME: Should be SystemNativeProcessorInformation */ + Status = NtQuerySystemInformation(SystemProcessorInformation, + &ProcInfo, + sizeof(ProcInfo), + 0); + if (!NT_SUCCESS(Status)) return; + + GetSystemInfoInternal(&BasicInfo, &ProcInfo, lpSystemInfo); +} + +/* + * @implemented + */ +BOOL +WINAPI +GetLogicalProcessorInformation(OUT PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, + IN OUT PDWORD ReturnLength) +{ + NTSTATUS Status; + + if (!ReturnLength) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Status = NtQuerySystemInformation(SystemLogicalProcessorInformation, + Buffer, + *ReturnLength, + ReturnLength); + + /* Normalize the error to what Win32 expects */ + if (Status == STATUS_INFO_LENGTH_MISMATCH) Status = STATUS_BUFFER_TOO_SMALL; + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetNumaHighestNodeNumber(OUT PULONG HighestNodeNumber) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetNumaNodeProcessorMask(IN UCHAR Node, + OUT PULONGLONG ProcessorMask) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetNumaProcessorNode(IN UCHAR Processor, + OUT PUCHAR NodeNumber) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetNumaAvailableMemoryNode(IN UCHAR Node, + OUT PULONGLONG AvailableBytes) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +DWORD +WINAPI +GetFirmwareEnvironmentVariableW(IN LPCWSTR lpName, + IN LPCWSTR lpGuid, + IN PVOID pValue, + IN DWORD nSize) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetFirmwareEnvironmentVariableW(IN LPCWSTR lpName, + IN LPCWSTR lpGuid, + IN PVOID pValue, + IN DWORD nSize) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +DWORD +WINAPI +GetFirmwareEnvironmentVariableA(IN LPCSTR lpName, + IN LPCSTR lpGuid, + IN PVOID pValue, + IN DWORD nSize) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetFirmwareEnvironmentVariableA(IN LPCSTR lpName, + IN LPCSTR lpGuid, + IN PVOID pValue, + IN DWORD nSize) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +UINT +WINAPI +EnumSystemFirmwareTables(IN DWORD FirmwareTableProviderSignature, + OUT PVOID pFirmwareTableBuffer, + IN DWORD BufferSize) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +UINT +WINAPI +GetSystemFirmwareTable(IN DWORD FirmwareTableProviderSignature, + IN DWORD FirmwareTableID, + OUT PVOID pFirmwareTableBuffer, + IN DWORD BufferSize) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetSystemFileCacheSize(OUT PSIZE_T lpMinimumFileCacheSize, + OUT PSIZE_T lpMaximumFileCacheSize, + OUT PDWORD lpFlags) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetSystemFileCacheSize(IN SIZE_T MinimumFileCacheSize, + IN SIZE_T MaximumFileCacheSize, + IN DWORD Flags) +{ + STUB; + return FALSE; +} diff --git a/dll/win32/kernel32/thread/thread.c b/dll/win32/kernel32/client/thread.c similarity index 75% rename from dll/win32/kernel32/thread/thread.c rename to dll/win32/kernel32/client/thread.c index 055342a0d39..13975dfaad1 100644 --- a/dll/win32/kernel32/thread/thread.c +++ b/dll/win32/kernel32/client/thread.c @@ -52,22 +52,34 @@ WINAPI BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter) { - volatile UINT uExitCode = 0; - /* Attempt to call the Thread Start Address */ _SEH2_TRY { + /* Legacy check which is still used today for Win32 threads */ + if (NtCurrentTeb()->NtTib.Version == (30 << 8)) // OS/2 V3.0 ("Cruiser") + { + /* This registers the termination port with CSRSS */ + if (!BaseRunningInServerProcess) CsrNewThread(); + } + /* Get the exit code from the Thread Start */ - uExitCode = (lpStartAddress)((PVOID)lpParameter); + ExitThread((lpStartAddress)((PVOID)lpParameter)); } _SEH2_EXCEPT(BaseThreadExceptionFilter(_SEH2_GetExceptionInformation())) { /* Get the Exit code from the SEH Handler */ - uExitCode = _SEH2_GetExceptionCode(); - } _SEH2_END; - - /* Exit the Thread */ - ExitThread(uExitCode); + if (!BaseRunningInServerProcess) + { + /* Kill the whole process, usually */ + ExitProcess(_SEH2_GetExceptionCode()); + } + else + { + /* If running inside CSRSS, kill just this thread */ + ExitThread(_SEH2_GetExceptionCode()); + } + } + _SEH2_END; } /* @@ -132,7 +144,7 @@ CreateRemoteThread(HANDLE hProcess, &InitialTeb); if(!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -160,7 +172,7 @@ CreateRemoteThread(HANDLE hProcess, if(!NT_SUCCESS(Status)) { BasepFreeStack(hProcess, &InitialTeb); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -230,7 +242,7 @@ CreateRemoteThread(HANDLE hProcess, { ASSERT(FALSE); } - + /* Success */ if(lpThreadId) *lpThreadId = HandleToUlong(ClientId.UniqueThread); @@ -310,7 +322,7 @@ OpenThread(DWORD dwDesiredAccess, &ClientId); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -368,7 +380,7 @@ GetThreadTimes(HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return(FALSE); } @@ -392,7 +404,7 @@ GetThreadContext(HANDLE hThread, Status = NtGetContextThread(hThread, lpContext); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -412,7 +424,7 @@ SetThreadContext(HANDLE hThread, Status = NtSetContextThread(hThread, (PCONTEXT)lpContext); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -437,7 +449,7 @@ GetExitCodeThread(HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return(FALSE); } @@ -458,7 +470,7 @@ ResumeThread(HANDLE hThread) Status = NtResumeThread(hThread, &PreviousResumeCount); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -484,7 +496,7 @@ TerminateThread(HANDLE hThread, Status = NtTerminateThread(hThread, dwExitCode); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -504,7 +516,7 @@ SuspendThread(HANDLE hThread) Status = NtSuspendThread(hThread, &PreviousSuspendCount); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -532,7 +544,7 @@ SetThreadAffinityMask(HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -542,7 +554,7 @@ SetThreadAffinityMask(HANDLE hThread, sizeof(KAFFINITY)); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); ThreadBasic.AffinityMask = 0; } @@ -578,7 +590,7 @@ SetThreadPriority(HANDLE hThread, if (!NT_SUCCESS(Status)) { /* Failure */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -605,17 +617,19 @@ GetThreadPriority(HANDLE hThread) if (!NT_SUCCESS(Status)) { /* Failure */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return THREAD_PRIORITY_ERROR_RETURN; } - /* Do some conversions for out of boundary values */ - if (ThreadBasic.BasePriority > THREAD_BASE_PRIORITY_MAX) + /* Do some conversions for saturation values */ + if (ThreadBasic.BasePriority == ((HIGH_PRIORITY + 1) / 2)) { + /* Win32 calls this "time critical" */ ThreadBasic.BasePriority = THREAD_PRIORITY_TIME_CRITICAL; } - else if (ThreadBasic.BasePriority < THREAD_BASE_PRIORITY_MIN) + else if (ThreadBasic.BasePriority == -((HIGH_PRIORITY + 1) / 2)) { + /* Win32 calls this "idle" */ ThreadBasic.BasePriority = THREAD_PRIORITY_IDLE; } @@ -641,7 +655,7 @@ GetThreadPriorityBoost(IN HANDLE hThread, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -668,7 +682,7 @@ SetThreadPriorityBoost(IN HANDLE hThread, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -698,7 +712,7 @@ GetThreadSelectorEntry(IN HANDLE hThread, if (!NT_SUCCESS(Status)) { /* Fail */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -727,7 +741,7 @@ SetThreadIdealProcessor(HANDLE hThread, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -750,7 +764,7 @@ GetProcessIdOfThread(HANDLE Thread) NULL); if(!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -773,7 +787,7 @@ GetThreadId(HANDLE Thread) NULL); if(!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -809,13 +823,22 @@ QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData) (PVOID)dwData, NULL); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } return 1; } +BOOL +WINAPI +SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes) +{ + STUB; + return FALSE; +} + + /* * @implemented */ @@ -843,53 +866,11 @@ GetThreadIOPendingFlag(HANDLE hThread, return TRUE; } - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } -/* - * @implemented - */ -VOID WINAPI -Sleep(DWORD dwMilliseconds) -{ - SleepEx(dwMilliseconds, FALSE); - return; -} - - -/* - * @implemented - */ -DWORD WINAPI -SleepEx(DWORD dwMilliseconds, - BOOL bAlertable) -{ - LARGE_INTEGER Interval; - NTSTATUS errCode; - - if (dwMilliseconds != INFINITE) - { - /* - * System time units are 100 nanoseconds (a nanosecond is a billionth of - * a second). - */ - Interval.QuadPart = -((LONGLONG)dwMilliseconds * 10000); - } - else - { - /* Approximately 292000 years hence */ - Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL; - } - -dowait: - errCode = NtDelayExecution ((BOOLEAN)bAlertable, &Interval); - if ((bAlertable) && (errCode == STATUS_ALERTED)) goto dowait; - return (errCode == STATUS_USER_APC) ? WAIT_IO_COMPLETION : 0; -} - - typedef struct _QUEUE_USER_WORKITEM_CONTEXT { LPTHREAD_START_ROUTINE Function; @@ -957,117 +938,248 @@ QueueUserWorkItem( 0, WorkItemContext); - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } return TRUE; } - /* * @implemented */ -BOOL +DWORD WINAPI -RegisterWaitForSingleObject( - PHANDLE phNewWaitObject, - HANDLE hObject, - WAITORTIMERCALLBACK Callback, - PVOID Context, - ULONG dwMilliseconds, - ULONG dwFlags - ) +TlsAlloc(VOID) { - NTSTATUS Status = RtlRegisterWait(phNewWaitObject, - hObject, - Callback, - Context, - dwMilliseconds, - dwFlags); + ULONG Index; + PTEB Teb; + PPEB Peb; + + /* Get the PEB and TEB, lock the PEB */ + Teb = NtCurrentTeb(); + Peb = Teb->ProcessEnvironmentBlock; + RtlAcquirePebLock(); + + /* Try to get regular TEB slot */ + Index = RtlFindClearBitsAndSet(Peb->TlsBitmap, 1, 0); + if (Index != 0xFFFFFFFF) + { + /* Clear the value. */ + Teb->TlsSlots[Index] = 0; + RtlReleasePebLock(); + return Index; + } - if (!NT_SUCCESS(Status)) + /* If it fails, try to find expansion TEB slot. */ + Index = RtlFindClearBitsAndSet(Peb->TlsExpansionBitmap, 1, 0); + if (Index != 0xFFFFFFFF) { - SetLastErrorByStatus(Status); - return FALSE; + /* Is there no expansion slot yet? */ + if (!Teb->TlsExpansionSlots) + { + /* Allocate an array */ + Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TLS_EXPANSION_SLOTS * + sizeof(PVOID)); + } + + /* Did we get an array? */ + if (!Teb->TlsExpansionSlots) + { + /* Fail */ + RtlClearBits(Peb->TlsExpansionBitmap, Index, 1); + Index = 0xFFFFFFFF; + BaseSetLastNTError(STATUS_NO_MEMORY); + } + else + { + /* Clear the value. */ + Teb->TlsExpansionSlots[Index] = 0; + Index += TLS_MINIMUM_AVAILABLE; + } + } + else + { + /* Fail */ + BaseSetLastNTError(STATUS_NO_MEMORY); } - return TRUE; -} + /* Release the lock and return */ + RtlReleasePebLock(); + return Index; +} /* * @implemented */ -HANDLE +BOOL WINAPI -RegisterWaitForSingleObjectEx( - HANDLE hObject, - WAITORTIMERCALLBACK Callback, - PVOID Context, - ULONG dwMilliseconds, - ULONG dwFlags - ) +TlsFree(IN DWORD Index) { + BOOL BitSet; + PPEB Peb; + ULONG TlsIndex; + PVOID TlsBitmap; NTSTATUS Status; - HANDLE hNewWaitObject; - Status = RtlRegisterWait(&hNewWaitObject, - hObject, - Callback, - Context, - dwMilliseconds, - dwFlags); + /* Acquire the PEB lock and grab the PEB */ + Peb = NtCurrentPeb(); + RtlAcquirePebLock(); - if (!NT_SUCCESS(Status)) + /* Check if the index is too high */ + if (Index >= TLS_MINIMUM_AVAILABLE) { - SetLastErrorByStatus(Status); - return NULL; + /* Check if it can fit in the expansion slots */ + TlsIndex = Index - TLS_MINIMUM_AVAILABLE; + if (TlsIndex >= TLS_EXPANSION_SLOTS) + { + /* It's invalid */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + RtlReleasePebLock(); + return FALSE; + } + else + { + /* Use the expansion bitmap */ + TlsBitmap = Peb->TlsExpansionBitmap; + Index = TlsIndex; + } + } + else + { + /* Use the normal bitmap */ + TlsBitmap = Peb->TlsBitmap; } - return hNewWaitObject; -} + /* Check if the index was set */ + BitSet = RtlAreBitsSet(TlsBitmap, Index, 1); + if (BitSet) + { + /* Tell the kernel to free the TLS cells */ + Status = NtSetInformationThread(NtCurrentThread(), + ThreadZeroTlsCell, + &Index, + sizeof(DWORD)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + RtlReleasePebLock(); + return FALSE; + } + /* Clear the bit */ + RtlClearBits(TlsBitmap, Index, 1); + } + else + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + RtlReleasePebLock(); + return FALSE; + } + + /* Done! */ + RtlReleasePebLock(); + return TRUE; +} /* * @implemented */ -BOOL +LPVOID WINAPI -UnregisterWait( - HANDLE WaitHandle - ) +TlsGetValue(IN DWORD Index) { - NTSTATUS Status = RtlDeregisterWaitEx(WaitHandle, NULL); + PTEB Teb; - if (!NT_SUCCESS(Status)) + /* Get the TEB and clear the last error */ + Teb = NtCurrentTeb(); + Teb->LastErrorValue = 0; + + /* Check for simple TLS index */ + if (Index < TLS_MINIMUM_AVAILABLE) { - SetLastErrorByStatus(Status); - return FALSE; + /* Return it */ + return Teb->TlsSlots[Index]; } - return TRUE; -} + /* Check for valid index */ + if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return NULL; + } + /* The expansion slots are allocated on demand, so check for it. */ + Teb->LastErrorValue = 0; + if (!Teb->TlsExpansionSlots) return NULL; + + /* Return the value from the expansion slots */ + return Teb->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE]; +} /* * @implemented */ BOOL WINAPI -UnregisterWaitEx( - HANDLE WaitHandle, - HANDLE CompletionEvent - ) +TlsSetValue(IN DWORD Index, + IN LPVOID Value) { - NTSTATUS Status = RtlDeregisterWaitEx(WaitHandle, CompletionEvent); + DWORD TlsIndex; + PTEB Teb = NtCurrentTeb(); - if (!NT_SUCCESS(Status)) + /* Check for simple TLS index */ + if (Index < TLS_MINIMUM_AVAILABLE) { - SetLastErrorByStatus(Status); + /* Return it */ + Teb->TlsSlots[Index] = Value; + return TRUE; + } + + /* Check if this is an expansion slot */ + TlsIndex = Index - TLS_MINIMUM_AVAILABLE; + if (TlsIndex >= TLS_EXPANSION_SLOTS) + { + /* Fail */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } + /* Do we not have expansion slots? */ + if (!Teb->TlsExpansionSlots) + { + /* Get the PEB lock to see if we still need them */ + RtlAcquirePebLock(); + if (!Teb->TlsExpansionSlots) + { + /* Allocate them */ + Teb->TlsExpansionSlots = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TLS_EXPANSION_SLOTS * + sizeof(PVOID)); + if (!Teb->TlsExpansionSlots) + { + /* Fail */ + RtlReleasePebLock(); + BaseSetLastNTError(STATUS_NO_MEMORY); + return FALSE; + } + } + + /* Release the lock */ + RtlReleasePebLock(); + } + + /* Write the value */ + Teb->TlsExpansionSlots[TlsIndex] = Value; + + /* Success */ return TRUE; } + /* EOF */ diff --git a/dll/win32/kernel32/client/time.c b/dll/win32/kernel32/client/time.c new file mode 100644 index 00000000000..992f063b124 --- /dev/null +++ b/dll/win32/kernel32/client/time.c @@ -0,0 +1,617 @@ +/* $Id: time.c 52770 2011-07-22 02:13:57Z ion $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/time.c + * PURPOSE: Time conversion functions + * PROGRAMMER: Ariadne + * DOSDATE and DOSTIME structures from Onno Hovers + * UPDATE HISTORY: + * Created 19/01/99 + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +IsTimeZoneRedirectionEnabled(VOID) +{ + /* Return if a TS Timezone ID is active */ + return (BaseStaticServerData->TermsrvClientTimeZoneId != TIME_ZONE_ID_INVALID); +} + +/* + * @implemented + */ +BOOL +WINAPI +FileTimeToDosDateTime(IN CONST FILETIME *lpFileTime, + OUT LPWORD lpFatDate, + OUT LPWORD lpFatTime) +{ + LARGE_INTEGER FileTime; + TIME_FIELDS TimeFields; + + FileTime.HighPart = lpFileTime->dwHighDateTime; + FileTime.LowPart = lpFileTime->dwLowDateTime; + + if (FileTime.QuadPart < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlTimeToTimeFields(&FileTime, &TimeFields); + if ((TimeFields.Year < 1980) || (TimeFields.Year > 2107)) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return FALSE; + } + + *lpFatDate = (TimeFields.Day) | + (TimeFields.Month << 5) | + ((TimeFields.Year - 1980) << 9); + *lpFatTime = (TimeFields.Second >> 1) | + (TimeFields.Minute << 5) | + (TimeFields.Hour << 16); + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DosDateTimeToFileTime(IN WORD wFatDate, + IN WORD wFatTime, + OUT LPFILETIME lpFileTime) +{ + TIME_FIELDS TimeFields; + LARGE_INTEGER SystemTime; + + TimeFields.Year = (wFatDate >> 9) + 1980; + TimeFields.Month = (wFatDate >> 5) & 0xF; + TimeFields.Day = (wFatDate & 0x1F); + TimeFields.Hour = (wFatTime >> 11); + TimeFields.Minute = (wFatTime >> 5) & 0x3F; + TimeFields.Second = (wFatTime & 0x1F) << 1; + TimeFields.Milliseconds = 0; + + if (RtlTimeFieldsToTime(&TimeFields, &SystemTime)) + { + lpFileTime->dwLowDateTime = SystemTime.LowPart; + lpFileTime->dwHighDateTime = SystemTime.HighPart; + return TRUE; + } + + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return FALSE; +} + +/* + * @implemented + */ +LONG +WINAPI +CompareFileTime(IN CONST FILETIME *lpFileTime1, + IN CONST FILETIME *lpFileTime2) +{ + LARGE_INTEGER Time1, Time2, Diff; + + Time1.LowPart = lpFileTime1->dwLowDateTime; + Time2.LowPart = lpFileTime2->dwLowDateTime; + Time1.HighPart = lpFileTime1->dwHighDateTime; + Time2.HighPart = lpFileTime2->dwHighDateTime; + + Diff.QuadPart = Time1.QuadPart - Time2.QuadPart; + + if (Diff.HighPart < 0) return -1; + if (Diff.QuadPart == 0) return 0; + return 1; +} + +/* + * @implemented + */ +VOID +WINAPI +GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime) +{ + LARGE_INTEGER SystemTime; + + do + { + SystemTime.HighPart = SharedUserData->SystemTime.High1Time; + SystemTime.LowPart = SharedUserData->SystemTime.LowPart; + } + while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time); + + lpFileTime->dwLowDateTime = SystemTime.LowPart; + lpFileTime->dwHighDateTime = SystemTime.HighPart; +} + +/* + * @implemented + */ +BOOL +WINAPI +SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, + OUT LPFILETIME lpFileTime) +{ + TIME_FIELDS TimeFields; + LARGE_INTEGER liTime; + + TimeFields.Year = lpSystemTime->wYear; + TimeFields.Month = lpSystemTime->wMonth; + TimeFields.Day = lpSystemTime->wDay; + TimeFields.Hour = lpSystemTime->wHour; + TimeFields.Minute = lpSystemTime->wMinute; + TimeFields.Second = lpSystemTime->wSecond; + TimeFields.Milliseconds = lpSystemTime->wMilliseconds; + + if (RtlTimeFieldsToTime(&TimeFields, &liTime)) + { + lpFileTime->dwLowDateTime = liTime.u.LowPart; + lpFileTime->dwHighDateTime = liTime.u.HighPart; + return TRUE; + } + + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, + OUT LPSYSTEMTIME lpSystemTime) +{ + TIME_FIELDS TimeFields; + LARGE_INTEGER liTime; + + liTime.u.LowPart = lpFileTime->dwLowDateTime; + liTime.u.HighPart = lpFileTime->dwHighDateTime; + if (liTime.QuadPart < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlTimeToTimeFields(&liTime, &TimeFields); + + lpSystemTime->wYear = TimeFields.Year; + lpSystemTime->wMonth = TimeFields.Month; + lpSystemTime->wDay = TimeFields.Day; + lpSystemTime->wHour = TimeFields.Hour; + lpSystemTime->wMinute = TimeFields.Minute; + lpSystemTime->wSecond = TimeFields.Second; + lpSystemTime->wMilliseconds = TimeFields.Milliseconds; + lpSystemTime->wDayOfWeek = TimeFields.Weekday; + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, + OUT LPFILETIME lpLocalFileTime) +{ + LARGE_INTEGER TimeZoneBias, FileTime; + volatile KSYSTEM_TIME *TimePtr; + + TimePtr = IsTimeZoneRedirectionEnabled() ? + &BaseStaticServerData->ktTermsrvClientBias : + &SharedUserData->TimeZoneBias; + do + { + TimeZoneBias.HighPart = TimePtr->High1Time; + TimeZoneBias.LowPart = TimePtr->LowPart; + } + while (TimeZoneBias.HighPart != TimePtr->High2Time); + + FileTime.LowPart = lpFileTime->dwLowDateTime; + FileTime.HighPart = lpFileTime->dwHighDateTime; + + FileTime.QuadPart -= TimeZoneBias.QuadPart; + + lpLocalFileTime->dwLowDateTime = FileTime.LowPart; + lpLocalFileTime->dwHighDateTime = FileTime.HighPart; + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +LocalFileTimeToFileTime(IN CONST FILETIME *lpLocalFileTime, + OUT LPFILETIME lpFileTime) +{ + LARGE_INTEGER TimeZoneBias, FileTime; + volatile KSYSTEM_TIME *TimePtr; + + TimePtr = IsTimeZoneRedirectionEnabled() ? + &BaseStaticServerData->ktTermsrvClientBias : + &SharedUserData->TimeZoneBias; + + do + { + TimeZoneBias.HighPart = TimePtr->High1Time; + TimeZoneBias.LowPart = TimePtr->LowPart; + } + while (TimeZoneBias.HighPart != TimePtr->High2Time); + + FileTime.LowPart = lpLocalFileTime->dwLowDateTime; + FileTime.HighPart = lpLocalFileTime->dwHighDateTime; + + FileTime.QuadPart += TimeZoneBias.QuadPart; + + lpFileTime->dwLowDateTime = FileTime.LowPart; + lpFileTime->dwHighDateTime = FileTime.HighPart; + + return TRUE; +} + +/* + * @implemented + */ +VOID +WINAPI +GetLocalTime(OUT LPSYSTEMTIME lpSystemTime) +{ + LARGE_INTEGER SystemTime, TimeZoneBias; + TIME_FIELDS TimeFields; + volatile KSYSTEM_TIME *TimePtr; + + do + { + SystemTime.HighPart = SharedUserData->SystemTime.High1Time; + SystemTime.LowPart = SharedUserData->SystemTime.LowPart; + } + while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time); + + TimePtr = IsTimeZoneRedirectionEnabled() ? + &BaseStaticServerData->ktTermsrvClientBias : + &SharedUserData->TimeZoneBias; + do + { + TimeZoneBias.HighPart = TimePtr->High1Time; + TimeZoneBias.LowPart = TimePtr->LowPart; + } + while (TimeZoneBias.HighPart != TimePtr->High2Time); + + SystemTime.QuadPart -= TimeZoneBias.QuadPart; + RtlTimeToTimeFields(&SystemTime, &TimeFields); + + lpSystemTime->wYear = TimeFields.Year; + lpSystemTime->wMonth = TimeFields.Month; + lpSystemTime->wDay = TimeFields.Day; + lpSystemTime->wHour = TimeFields.Hour; + lpSystemTime->wMinute = TimeFields.Minute; + lpSystemTime->wSecond = TimeFields.Second; + lpSystemTime->wMilliseconds = TimeFields.Milliseconds; + lpSystemTime->wDayOfWeek = TimeFields.Weekday; +} + +/* + * @implemented + */ +VOID +WINAPI +GetSystemTime(OUT LPSYSTEMTIME lpSystemTime) +{ + LARGE_INTEGER SystemTime; + TIME_FIELDS TimeFields; + + do + { + SystemTime.HighPart = SharedUserData->SystemTime.High1Time; + SystemTime.LowPart = SharedUserData->SystemTime.LowPart; + } + while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time); + + RtlTimeToTimeFields(&SystemTime, &TimeFields); + + lpSystemTime->wYear = TimeFields.Year; + lpSystemTime->wMonth = TimeFields.Month; + lpSystemTime->wDay = TimeFields.Day; + lpSystemTime->wHour = TimeFields.Hour; + lpSystemTime->wMinute = TimeFields.Minute; + lpSystemTime->wSecond = TimeFields.Second; + lpSystemTime->wMilliseconds = TimeFields.Milliseconds; + lpSystemTime->wDayOfWeek = TimeFields.Weekday; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetLocalTime(IN CONST SYSTEMTIME *lpSystemTime) +{ + LARGE_INTEGER NewSystemTime, TimeZoneBias; + NTSTATUS Status; + ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE; + TIME_FIELDS TimeFields; + PVOID State; + volatile KSYSTEM_TIME *TimePtr; + + TimePtr = IsTimeZoneRedirectionEnabled() ? + &BaseStaticServerData->ktTermsrvClientBias : + &SharedUserData->TimeZoneBias; + do + { + TimeZoneBias.HighPart = TimePtr->High1Time; + TimeZoneBias.LowPart = TimePtr->LowPart; + } + while (TimeZoneBias.HighPart != TimePtr->High2Time); + + TimeFields.Year = lpSystemTime->wYear; + TimeFields.Month = lpSystemTime->wMonth; + TimeFields.Day = lpSystemTime->wDay; + TimeFields.Hour = lpSystemTime->wHour; + TimeFields.Minute = lpSystemTime->wMinute; + TimeFields.Second = lpSystemTime->wSecond; + TimeFields.Milliseconds = lpSystemTime->wMilliseconds; + + if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime)) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return FALSE; + } + + NewSystemTime.QuadPart += TimeZoneBias.QuadPart; + + Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State); + Status = STATUS_SUCCESS; + if (NT_SUCCESS(Status)) + { + Status = NtSetSystemTime(&NewSystemTime, NULL); + RtlReleasePrivilege(State); + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetSystemTime(IN CONST SYSTEMTIME *lpSystemTime) +{ + LARGE_INTEGER NewSystemTime; + NTSTATUS Status; + ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE; + TIME_FIELDS TimeFields; + PVOID State; + + TimeFields.Year = lpSystemTime->wYear; + TimeFields.Month = lpSystemTime->wMonth; + TimeFields.Day = lpSystemTime->wDay; + TimeFields.Hour = lpSystemTime->wHour; + TimeFields.Minute = lpSystemTime->wMinute; + TimeFields.Second = lpSystemTime->wSecond; + TimeFields.Milliseconds = lpSystemTime->wMilliseconds; + + if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime)) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return FALSE; + } + + Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State); + Status = STATUS_SUCCESS; + if (NT_SUCCESS(Status)) + { + Status = NtSetSystemTime(&NewSystemTime, NULL); + RtlReleasePrivilege(State); + } + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetTickCount(VOID) +{ + ULARGE_INTEGER TickCount; + + while (TRUE) + { + TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time; + TickCount.LowPart = SharedUserData->TickCount.LowPart; + + if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) + break; + + YieldProcessor(); + } + + return (ULONG)((UInt32x32To64(TickCount.LowPart, + SharedUserData->TickCountMultiplier) >> 24) + + UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF, + SharedUserData->TickCountMultiplier)); + +} + +/* + * @implemented + */ +BOOL +WINAPI +GetSystemTimeAdjustment(OUT PDWORD lpTimeAdjustment, + OUT PDWORD lpTimeIncrement, + OUT PBOOL lpTimeAdjustmentDisabled) +{ + SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemTimeAdjustmentInformation, + &TimeInfo, + sizeof(TimeInfo), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + *lpTimeAdjustment = (DWORD)TimeInfo.TimeAdjustment; + *lpTimeIncrement = (DWORD)TimeInfo.TimeIncrement; + *lpTimeAdjustmentDisabled = (BOOL)TimeInfo.Enable; + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetSystemTimeAdjustment(IN DWORD dwTimeAdjustment, + IN BOOL bTimeAdjustmentDisabled) +{ + NTSTATUS Status; + SYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo; + + TimeInfo.TimeAdjustment = (ULONG)dwTimeAdjustment; + TimeInfo.Enable = (BOOLEAN)bTimeAdjustmentDisabled; + + Status = NtSetSystemInformation(SystemTimeAdjustmentInformation, + &TimeInfo, + sizeof(TimeInfo)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetSystemTimes(OUT LPFILETIME lpIdleTime OPTIONAL, + OUT LPFILETIME lpKernelTime OPTIONAL, + OUT LPFILETIME lpUserTime OPTIONAL) +{ + PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcPerfInfo; + LARGE_INTEGER TotalUserTime, TotalKernTime, TotalIdleTime; + SIZE_T BufferSize, ReturnLength; + ULONG i; + NTSTATUS Status; + + TotalUserTime.QuadPart = TotalKernTime.QuadPart = TotalIdleTime.QuadPart = 0; + + BufferSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * + BaseStaticServerData->SysInfo.NumberOfProcessors; + + ProcPerfInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize); + if (!ProcPerfInfo) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return FALSE; + } + + Status = ZwQuerySystemInformation(SystemProcessorPerformanceInformation, + ProcPerfInfo, + BufferSize, + &ReturnLength); + if ((NT_SUCCESS(Status)) && (ReturnLength == BufferSize)) + { + if (lpIdleTime) + { + for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++) + { + TotalIdleTime.QuadPart += ProcPerfInfo[i].IdleTime.QuadPart; + } + + lpIdleTime->dwLowDateTime = TotalIdleTime.LowPart; + lpIdleTime->dwHighDateTime = TotalIdleTime.HighPart; + } + + if (lpKernelTime) + { + for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++) + { + TotalKernTime.QuadPart += ProcPerfInfo[i].KernelTime.QuadPart; + } + + lpKernelTime->dwLowDateTime = TotalKernTime.LowPart; + lpKernelTime->dwHighDateTime = TotalKernTime.HighPart; + } + + if (lpUserTime) + { + for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++) + { + TotalUserTime.QuadPart += ProcPerfInfo[i].UserTime.QuadPart; + } + + lpUserTime->dwLowDateTime = TotalUserTime.LowPart; + lpUserTime->dwHighDateTime = TotalUserTime.HighPart; + } + } + else if (NT_SUCCESS(Status)) + { + Status = STATUS_INTERNAL_ERROR; + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, ProcPerfInfo); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetClientTimeZoneInformation(IN CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation) +{ + STUB; + return 0; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/timerqueue.c b/dll/win32/kernel32/client/timerqueue.c new file mode 100644 index 00000000000..5a24a258b9f --- /dev/null +++ b/dll/win32/kernel32/client/timerqueue.c @@ -0,0 +1,321 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: See COPYING in the top level directory + * FILE: dll/win32/kernel32/client/timerqueue.c + * PURPOSE: Timer Queue Functions + * PROGRAMMERS: Thomas Weidenmueller + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +HANDLE BasepDefaultTimerQueue = NULL; + +/* PRIVATE FUNCTIONS **********************************************************/ + +/* FIXME - make this thread safe */ +BOOL +WINAPI +BasepCreateDefaultTimerQueue(VOID) +{ + NTSTATUS Status; + + /* Create the timer queue */ + Status = RtlCreateTimerQueue(&BasepDefaultTimerQueue); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + DPRINT1("Unable to create the default timer queue!\n"); + return FALSE; + } + + return TRUE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + + +/* + * @implemented + */ +BOOL +WINAPI +CancelTimerQueueTimer(IN HANDLE TimerQueue, + IN HANDLE Timer) +{ + NTSTATUS Status; + + if (!TimerQueue) + { + /* Use the default timer queue */ + TimerQueue = BasepDefaultTimerQueue; + if (!TimerQueue) + { + /* A timer is being cancelled before one was created... fail */ + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + } + + /* Delete the timer */ + Status = RtlDeleteTimer(TimerQueue, Timer, NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +ChangeTimerQueueTimer(IN HANDLE TimerQueue, + IN HANDLE Timer, + IN ULONG DueTime, + IN ULONG Period) +{ + NTSTATUS Status; + + if (!TimerQueue) + { + /* Use the default timer queue */ + TimerQueue = BasepDefaultTimerQueue; + if (!TimerQueue) + { + /* A timer is being cancelled before one was created... fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + } + + /* Delete the timer */ + Status = RtlUpdateTimer(TimerQueue, Timer, DueTime, Period); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +CreateTimerQueue(VOID) +{ + HANDLE Handle; + NTSTATUS Status; + + /* Create the timer queue */ + Status = RtlCreateTimerQueue(&Handle); + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + return Handle; +} + +/* + * @implemented + */ +BOOL +WINAPI +CreateTimerQueueTimer(OUT PHANDLE phNewTimer, + IN HANDLE TimerQueue, + IN WAITORTIMERCALLBACK Callback, + IN PVOID Parameter, + IN DWORD DueTime, + IN DWORD Period, + IN ULONG Flags) +{ + NTSTATUS Status; + + /* Parameter is not optional -- clear it now */ + *phNewTimer = NULL; + + /* Check if no queue was given */ + if (!TimerQueue) + { + /* Create the queue if it didn't already exist */ + if (!(BasepDefaultTimerQueue) && !(BasepCreateDefaultTimerQueue())) + { + return FALSE; + } + + /* Use the default queue */ + TimerQueue = BasepDefaultTimerQueue; + } + + /* Create the timer. Note that no parameter checking is done here */ + Status = RtlCreateTimer(TimerQueue, + phNewTimer, + Callback, + Parameter, + DueTime, + Period, + Flags); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DeleteTimerQueue(IN HANDLE TimerQueue) +{ + /* We don't allow the user to delete the default timer queue */ + if (!TimerQueue) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + /* Delete the timer queue */ + RtlDeleteTimerQueueEx(TimerQueue, 0); + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DeleteTimerQueueEx(IN HANDLE TimerQueue, + IN HANDLE CompletionEvent) +{ + NTSTATUS Status; + + /* We don't allow the user to delete the default timer queue */ + if (!TimerQueue) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + /* Delete the timer queue */ + Status = RtlDeleteTimerQueueEx(TimerQueue, CompletionEvent); + if (((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING)) || + !(NT_SUCCESS(Status))) + { + /* In case CompletionEvent == NULL, RtlDeleteTimerQueueEx() returns before + all callback routines returned. We set the last error code to STATUS_PENDING + and return FALSE. In case CompletionEvent == INVALID_HANDLE_VALUE we only + can get here if another error occured. In case CompletionEvent is something + else, we get here and fail, even though it isn't really an error (if Status == STATUS_PENDING). + We also handle all other failures the same way. */ + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +DeleteTimerQueueTimer(IN HANDLE TimerQueue, + IN HANDLE Timer, + IN HANDLE CompletionEvent) +{ + NTSTATUS Status; + + if (!TimerQueue) + { + /* Use the default timer queue */ + TimerQueue = BasepDefaultTimerQueue; + if (!TimerQueue) + { + /* A timer is being cancelled before one was created... fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + } + + /* Delete the timer */ + Status = RtlDeleteTimer(TimerQueue, Timer, CompletionEvent); + if (((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING)) || + !(NT_SUCCESS(Status))) + { + /* In case CompletionEvent == NULL, RtlDeleteTimerQueueEx() returns before + all callback routines returned. We set the last error code to STATUS_PENDING + and return FALSE. In case CompletionEvent == INVALID_HANDLE_VALUE we only + can get here if another error occured. In case CompletionEvent is something + else, we get here and fail, even though it isn't really an error (if Status == STATUS_PENDING). + We also handle all other failures the same way. */ + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +HANDLE +WINAPI +SetTimerQueueTimer(IN HANDLE TimerQueue, + IN WAITORTIMERCALLBACK Callback, + IN PVOID Parameter, + IN DWORD DueTime, + IN DWORD Period, + IN BOOL PreferIo) +{ + HANDLE Timer; + NTSTATUS Status; + + /* Check if no queue was given */ + if (!TimerQueue) + { + /* Create the queue if it didn't already exist */ + if (!(BasepDefaultTimerQueue) && !(BasepCreateDefaultTimerQueue())) + { + return FALSE; + } + + /* Use the default queue */ + TimerQueue = BasepDefaultTimerQueue; + } + + /* Create the timer */ + Status = RtlCreateTimer(TimerQueue, + &Timer, + Callback, + Parameter, + DueTime, + Period, + PreferIo ? WT_EXECUTEINIOTHREAD : WT_EXECUTEDEFAULT); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + return Timer; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/toolhelp.c b/dll/win32/kernel32/client/toolhelp.c new file mode 100644 index 00000000000..ca2f558bd27 --- /dev/null +++ b/dll/win32/kernel32/client/toolhelp.c @@ -0,0 +1,1310 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/toolhelp.c + * PURPOSE: Toolhelp functions + * PROGRAMMER: Thomas Weidenmueller + * Robert Dickenson (robd@mok.lvcm.com) + * + * NOTES: Do NOT use the heap functions in here because they + * adulterate the heap statistics! + * + * UPDATE HISTORY: + * 10/30/2004 Implemented some parts (w3) + * Inspired by the book "Windows NT Native API" + * Created 05 January 2003 (robd) + */ + +#include + +#include + +#define NDEBUG +#include + +/* INTERNAL DEFINITIONS *******************************************************/ + +typedef struct _RTLP_HEAP_ENTRY +{ + ULONG Size; + USHORT Flags; + USHORT Unknown1; /* FIXME */ + ULONG Unknown2; /* FIXME */ + PVOID Address; +} RTLP_HEAP_ENTRY, *PRTLP_HEAP_ENTRY; + +#define CHECK_PARAM_SIZE(ptr, siz) \ + if((ptr) == NULL || (ptr)->dwSize != (siz)) \ + { \ + SetLastError(ERROR_INVALID_PARAMETER); \ + return FALSE; \ + } + +/* + * Tests in win showed that the dwSize field can be greater than the actual size + * of the structure for the ansi functions. I found this out by accidently + * forgetting to set the dwSize field in a test application and it just didn't + * work in ros but in win. + */ + +#define CHECK_PARAM_SIZEA(ptr, siz) \ + if((ptr) == NULL || (ptr)->dwSize < (siz)) \ + { \ + SetLastError(ERROR_INVALID_PARAMETER); \ + return FALSE; \ + } + +#define OffsetToPtr(Snapshot, Offset) \ + ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset)) + +typedef struct _TH32SNAPSHOT +{ + /* Heap list */ + ULONG HeapListCount; + ULONG HeapListIndex; + ULONG_PTR HeapListOffset; + /* Module list */ + ULONG ModuleListCount; + ULONG ModuleListIndex; + ULONG_PTR ModuleListOffset; + /* Process list */ + ULONG ProcessListCount; + ULONG ProcessListIndex; + ULONG_PTR ProcessListOffset; + /* Thread list */ + ULONG ThreadListCount; + ULONG ThreadListIndex; + ULONG_PTR ThreadListOffset; +} TH32SNAPSHOT, *PTH32SNAPSHOT; + +/* INTERNAL FUNCTIONS *********************************************************/ + +static VOID +TH32FreeAllocatedResources(PRTL_DEBUG_INFORMATION HeapDebug, + PRTL_DEBUG_INFORMATION ModuleDebug, + PVOID ProcThrdInfo, + SIZE_T ProcThrdInfoSize) +{ + if(HeapDebug != NULL) + { + RtlDestroyQueryDebugBuffer(HeapDebug); + } + if(ModuleDebug != NULL) + { + RtlDestroyQueryDebugBuffer(ModuleDebug); + } + + if(ProcThrdInfo != NULL) + { + NtFreeVirtualMemory(NtCurrentProcess(), + &ProcThrdInfo, + &ProcThrdInfoSize, + MEM_RELEASE); + } +} + +static NTSTATUS +TH32CreateSnapshot(DWORD dwFlags, + DWORD th32ProcessID, + PRTL_DEBUG_INFORMATION *HeapDebug, + PRTL_DEBUG_INFORMATION *ModuleDebug, + PVOID *ProcThrdInfo, + SIZE_T *ProcThrdInfoSize) +{ + NTSTATUS Status = STATUS_SUCCESS; + + *HeapDebug = NULL; + *ModuleDebug = NULL; + *ProcThrdInfo = NULL; + *ProcThrdInfoSize = 0; + + /* + * Allocate the debug information for a heap snapshot + */ + if(dwFlags & TH32CS_SNAPHEAPLIST) + { + *HeapDebug = RtlCreateQueryDebugBuffer(0, FALSE); + if(*HeapDebug != NULL) + { + Status = RtlQueryProcessDebugInformation(th32ProcessID, + RTL_DEBUG_QUERY_HEAPS, + *HeapDebug); + } + else + Status = STATUS_UNSUCCESSFUL; + } + + /* + * Allocate the debug information for a module snapshot + */ + if(dwFlags & TH32CS_SNAPMODULE && + NT_SUCCESS(Status)) + { + *ModuleDebug = RtlCreateQueryDebugBuffer(0, FALSE); + if(*ModuleDebug != NULL) + { + Status = RtlQueryProcessDebugInformation(th32ProcessID, + RTL_DEBUG_QUERY_MODULES, + *ModuleDebug); + } + else + Status = STATUS_UNSUCCESSFUL; + } + + /* + * Allocate enough memory for the system's process list + */ + + if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD) && + NT_SUCCESS(Status)) + { + for(;;) + { + (*ProcThrdInfoSize) += 0x10000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + ProcThrdInfo, + 0, + ProcThrdInfoSize, + MEM_COMMIT, + PAGE_READWRITE); + if(!NT_SUCCESS(Status)) + { + break; + } + + Status = NtQuerySystemInformation(SystemProcessInformation, + *ProcThrdInfo, + *ProcThrdInfoSize, + NULL); + if(Status == STATUS_INFO_LENGTH_MISMATCH) + { + NtFreeVirtualMemory(NtCurrentProcess(), + ProcThrdInfo, + ProcThrdInfoSize, + MEM_RELEASE); + *ProcThrdInfo = NULL; + } + else + { + break; + } + } + } + + /* + * Free resources in case of failure! + */ + + if(!NT_SUCCESS(Status)) + { + TH32FreeAllocatedResources(*HeapDebug, + *ModuleDebug, + *ProcThrdInfo, + *ProcThrdInfoSize); + } + + return Status; +} + +static NTSTATUS +TH32CreateSnapshotSectionInitialize(DWORD dwFlags, + DWORD th32ProcessID, + PRTL_DEBUG_INFORMATION HeapDebug, + PRTL_DEBUG_INFORMATION ModuleDebug, + PVOID ProcThrdInfo, + HANDLE *SectionHandle) +{ + PSYSTEM_PROCESS_INFORMATION ProcessInfo; + LPHEAPLIST32 HeapListEntry; + LPMODULEENTRY32W ModuleListEntry; + LPPROCESSENTRY32W ProcessListEntry; + LPTHREADENTRY32 ThreadListEntry; + OBJECT_ATTRIBUTES ObjectAttributes; + LARGE_INTEGER SSize, SOffset; + HANDLE hSection; + PTH32SNAPSHOT Snapshot; + ULONG_PTR DataOffset; + SIZE_T ViewSize; + ULONG i, nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0; + ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT); + PRTL_PROCESS_HEAPS hi = NULL; + PRTL_PROCESS_MODULES mi = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + /* + * Determine the required size for the heap snapshot + */ + if(dwFlags & TH32CS_SNAPHEAPLIST) + { + hi = (PRTL_PROCESS_HEAPS)HeapDebug->Heaps; + nHeaps = hi->NumberOfHeaps; + RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32); + } + + /* + * Determine the required size for the module snapshot + */ + if(dwFlags & TH32CS_SNAPMODULE) + { + mi = (PRTL_PROCESS_MODULES)ModuleDebug->Modules; + nModules = mi->NumberOfModules; + RequiredSnapshotSize += nModules * sizeof(MODULEENTRY32W); + } + + /* + * Determine the required size for the processes and threads snapshot + */ + if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD)) + { + ULONG ProcOffset = 0; + + ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; + do + { + ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); + nProcesses++; + nThreads += ProcessInfo->NumberOfThreads; + ProcOffset = ProcessInfo->NextEntryOffset; + } while(ProcOffset != 0); + + if(dwFlags & TH32CS_SNAPPROCESS) + { + RequiredSnapshotSize += nProcesses * sizeof(PROCESSENTRY32W); + } + if(dwFlags & TH32CS_SNAPTHREAD) + { + RequiredSnapshotSize += nThreads * sizeof(THREADENTRY32); + } + } + + /* + * Create and map the section + */ + + SSize.QuadPart = RequiredSnapshotSize; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + ((dwFlags & TH32CS_INHERIT) ? OBJ_INHERIT : 0), + NULL, + NULL); + + Status = NtCreateSection(&hSection, + SECTION_ALL_ACCESS, + &ObjectAttributes, + &SSize, + PAGE_READWRITE, + SEC_COMMIT, + NULL); + if(!NT_SUCCESS(Status)) + { + return Status; + } + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSection, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(!NT_SUCCESS(Status)) + { + NtClose(hSection); + return Status; + } + + RtlZeroMemory(Snapshot, sizeof(TH32SNAPSHOT)); + DataOffset = 0; + + /* + * Initialize the section data and fill it with all the data we collected + */ + + /* initialize the heap list */ + if(dwFlags & TH32CS_SNAPHEAPLIST) + { + Snapshot->HeapListCount = nHeaps; + Snapshot->HeapListOffset = DataOffset; + HeapListEntry = (LPHEAPLIST32)OffsetToPtr(Snapshot, DataOffset); + for(i = 0; i < nHeaps; i++) + { + HeapListEntry->dwSize = sizeof(HEAPLIST32); + HeapListEntry->th32ProcessID = th32ProcessID; + HeapListEntry->th32HeapID = (ULONG_PTR)hi->Heaps[i].BaseAddress; + HeapListEntry->dwFlags = hi->Heaps[i].Flags; + + HeapListEntry++; + } + + DataOffset += hi->NumberOfHeaps * sizeof(HEAPLIST32); + } + + /* initialize the module list */ + if(dwFlags & TH32CS_SNAPMODULE) + { + Snapshot->ModuleListCount = nModules; + Snapshot->ModuleListOffset = DataOffset; + ModuleListEntry = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, DataOffset); + for(i = 0; i < nModules; i++) + { + ModuleListEntry->dwSize = sizeof(MODULEENTRY32W); + ModuleListEntry->th32ModuleID = 1; /* no longer used, always set to one! */ + ModuleListEntry->th32ProcessID = th32ProcessID; + ModuleListEntry->GlblcntUsage = mi->Modules[i].LoadCount; + ModuleListEntry->ProccntUsage = mi->Modules[i].LoadCount; + ModuleListEntry->modBaseAddr = (BYTE*)mi->Modules[i].ImageBase; + ModuleListEntry->modBaseSize = mi->Modules[i].ImageSize; + ModuleListEntry->hModule = (HMODULE)mi->Modules[i].ImageBase; + + MultiByteToWideChar(CP_ACP, + 0, + &mi->Modules[i].FullPathName[mi->Modules[i].OffsetToFileName], + -1, + ModuleListEntry->szModule, + sizeof(ModuleListEntry->szModule) / sizeof(ModuleListEntry->szModule[0])); + + MultiByteToWideChar(CP_ACP, + 0, + mi->Modules[i].FullPathName, + -1, + ModuleListEntry->szExePath, + sizeof(ModuleListEntry->szExePath) / sizeof(ModuleListEntry->szExePath[0])); + + ModuleListEntry++; + } + + DataOffset += mi->NumberOfModules * sizeof(MODULEENTRY32W); + } + + /* initialize the process list */ + if(dwFlags & TH32CS_SNAPPROCESS) + { + ULONG ProcOffset = 0; + + Snapshot->ProcessListCount = nProcesses; + Snapshot->ProcessListOffset = DataOffset; + ProcessListEntry = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, DataOffset); + ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; + do + { + ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); + + ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W); + ProcessListEntry->cntUsage = 0; /* no longer used */ + ProcessListEntry->th32ProcessID = (ULONG_PTR)ProcessInfo->UniqueProcessId; + ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */ + ProcessListEntry->th32ModuleID = 0; /* no longer used */ + ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads; + ProcessListEntry->th32ParentProcessID = (ULONG_PTR)ProcessInfo->InheritedFromUniqueProcessId; + ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority; + ProcessListEntry->dwFlags = 0; /* no longer used */ + if(ProcessInfo->ImageName.Buffer != NULL) + { + lstrcpynW(ProcessListEntry->szExeFile, + ProcessInfo->ImageName.Buffer, + min(ProcessInfo->ImageName.Length / sizeof(WCHAR), sizeof(ProcessListEntry->szExeFile) / sizeof(ProcessListEntry->szExeFile[0]))); + } + else + { + lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]"); + } + + ProcessListEntry++; + + ProcOffset = ProcessInfo->NextEntryOffset; + } while(ProcOffset != 0); + + DataOffset += nProcesses * sizeof(PROCESSENTRY32W); + } + + /* initialize the thread list */ + if(dwFlags & TH32CS_SNAPTHREAD) + { + ULONG ProcOffset = 0; + + Snapshot->ThreadListCount = nThreads; + Snapshot->ThreadListOffset = DataOffset; + ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset); + ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; + do + { + PSYSTEM_THREAD_INFORMATION ThreadInfo; + ULONG n; + + ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); + ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1); + + for(n = 0; n < ProcessInfo->NumberOfThreads; n++) + { + ThreadListEntry->dwSize = sizeof(THREADENTRY32); + ThreadListEntry->cntUsage = 0; /* no longer used */ + ThreadListEntry->th32ThreadID = (ULONG_PTR)ThreadInfo->ClientId.UniqueThread; + ThreadListEntry->th32OwnerProcessID = (ULONG_PTR)ThreadInfo->ClientId.UniqueProcess; + ThreadListEntry->tpBasePri = ThreadInfo->BasePriority; + ThreadListEntry->tpDeltaPri = 0; /* no longer used */ + ThreadListEntry->dwFlags = 0; /* no longer used */ + + ThreadInfo++; + ThreadListEntry++; + } + + ProcOffset = ProcessInfo->NextEntryOffset; + } while(ProcOffset != 0); + } + + /* + * We're done, unmap the view and return the section handle + */ + + Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + + if(NT_SUCCESS(Status)) + { + *SectionHandle = hSection; + } + else + { + NtClose(hSection); + } + + return Status; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID) +{ + PRTL_DEBUG_INFORMATION DebugInfo; + PRTL_HEAP_INFORMATION Heap; + PRTLP_HEAP_ENTRY Block, LastBlock; + ULONG i; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32)); + + DebugInfo = RtlCreateQueryDebugBuffer(0, + FALSE); + if (DebugInfo == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + Status = RtlQueryProcessDebugInformation(th32ProcessID, + RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS, + DebugInfo); + + if (NT_SUCCESS(Status)) + { + Status = STATUS_NO_MORE_FILES; + + for (i = 0; + i != DebugInfo->Heaps->NumberOfHeaps; + i++) + { + Heap = &DebugInfo->Heaps->Heaps[i]; + + if ((ULONG_PTR)Heap->BaseAddress == th32HeapID) + { + lphe->hHandle = (HANDLE)Heap->BaseAddress; + lphe->dwAddress = 0; + lphe->dwBlockSize = 0; + lphe->dwFlags = 0; + lphe->dwLockCount = 0; + lphe->dwResvd = 0; + lphe->th32ProcessID = th32ProcessID; + lphe->th32HeapID = (ULONG_PTR)Heap->BaseAddress; + + Block = (PRTLP_HEAP_ENTRY)Heap->Entries; + LastBlock = Block + Heap->NumberOfEntries; + + while (Block != LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE)) + { + lphe->dwResvd++; + lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead); + Block++; + } + + if (Block != LastBlock && lphe->dwResvd != 0) + { + lphe->dwBlockSize = Block->Size; + + if (Block->Flags & 0x2F1) /* FIXME */ + lphe->dwFlags = LF32_FIXED; + else if (Block->Flags & 0x20) /* FIXME */ + lphe->dwFlags = LF32_MOVEABLE; + else if (Block->Flags & 0x100) /* FIXME */ + lphe->dwFlags = LF32_FREE; + + Status = STATUS_SUCCESS; + } + + break; + } + } + } + + RtlDestroyQueryDebugBuffer(DebugInfo); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Heap32Next(LPHEAPENTRY32 lphe) +{ + PRTL_DEBUG_INFORMATION DebugInfo; + PRTL_HEAP_INFORMATION Heap; + PRTLP_HEAP_ENTRY Block, LastBlock; + BOOLEAN FoundUncommitted = FALSE; + ULONG i; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32)); + + DebugInfo = RtlCreateQueryDebugBuffer(0, + FALSE); + if (DebugInfo == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + Status = RtlQueryProcessDebugInformation(lphe->th32ProcessID, + RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS, + DebugInfo); + + if (NT_SUCCESS(Status)) + { + Status = STATUS_NO_MORE_FILES; + + for (i = 0; + i != DebugInfo->Heaps->NumberOfHeaps; + i++) + { + Heap = &DebugInfo->Heaps->Heaps[i]; + + if ((ULONG_PTR)Heap->BaseAddress == lphe->th32HeapID) + { + if (++lphe->dwResvd < Heap->NumberOfEntries) + { + lphe->dwFlags = 0; + + Block = (PRTLP_HEAP_ENTRY)Heap->Entries + lphe->dwResvd; + LastBlock = (PRTLP_HEAP_ENTRY)Heap->Entries + Heap->NumberOfEntries; + + while (Block < LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE)) + { + lphe->dwResvd++; + lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead); + FoundUncommitted = TRUE; + Block++; + } + + if (Block < LastBlock) + { + if (!FoundUncommitted) + lphe->dwAddress += lphe->dwBlockSize; + + lphe->dwBlockSize = Block->Size; + + if (Block->Flags & 0x2F1) /* FIXME */ + lphe->dwFlags = LF32_FIXED; + else if (Block->Flags & 0x20) /* FIXME */ + lphe->dwFlags = LF32_MOVEABLE; + else if (Block->Flags & 0x100) /* FIXME */ + lphe->dwFlags = LF32_FREE; + + Status = STATUS_SUCCESS; + } + } + + break; + } + } + } + + RtlDestroyQueryDebugBuffer(DebugInfo); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; + +} + + +/* + * @implemented + */ +BOOL +WINAPI +Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->HeapListCount > 0) + { + LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset); + Snapshot->HeapListIndex = 1; + RtlCopyMemory(lphl, &Entries[0], sizeof(HEAPLIST32)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->HeapListCount > 0 && + Snapshot->HeapListIndex < Snapshot->HeapListCount) + { + LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset); + RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme) +{ + MODULEENTRY32W me; + BOOL Ret; + + CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32)); + + me.dwSize = sizeof(MODULEENTRY32W); + + Ret = Module32FirstW(hSnapshot, &me); + if(Ret) + { + lpme->th32ModuleID = me.th32ModuleID; + lpme->th32ProcessID = me.th32ProcessID; + lpme->GlblcntUsage = me.GlblcntUsage; + lpme->ProccntUsage = me.ProccntUsage; + lpme->modBaseAddr = me.modBaseAddr; + lpme->modBaseSize = me.modBaseSize; + lpme->hModule = me.hModule; + + WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0); + WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0); + } + + return Ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->ModuleListCount > 0) + { + LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset); + Snapshot->ModuleListIndex = 1; + RtlCopyMemory(lpme, &Entries[0], sizeof(MODULEENTRY32W)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme) +{ + MODULEENTRY32W me; + BOOL Ret; + + CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32)); + + me.dwSize = sizeof(MODULEENTRY32W); + + Ret = Module32NextW(hSnapshot, &me); + if(Ret) + { + lpme->th32ModuleID = me.th32ModuleID; + lpme->th32ProcessID = me.th32ProcessID; + lpme->GlblcntUsage = me.GlblcntUsage; + lpme->ProccntUsage = me.ProccntUsage; + lpme->modBaseAddr = me.modBaseAddr; + lpme->modBaseSize = me.modBaseSize; + lpme->hModule = me.hModule; + + WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0); + WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0); + } + + return Ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if((Snapshot->ModuleListCount > 0) && + (Snapshot->ModuleListIndex < Snapshot->ModuleListCount)) + { + LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset); + RtlCopyMemory(lpme, &Entries[Snapshot->ModuleListIndex++], sizeof(MODULEENTRY32W)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe) +{ + PROCESSENTRY32W pe; + BOOL Ret; + + CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32)); + + pe.dwSize = sizeof(PROCESSENTRY32W); + + Ret = Process32FirstW(hSnapshot, &pe); + if(Ret) + { + lppe->cntUsage = pe.cntUsage; + lppe->th32ProcessID = pe.th32ProcessID; + lppe->th32DefaultHeapID = pe.th32DefaultHeapID; + lppe->th32ModuleID = pe.th32ModuleID; + lppe->cntThreads = pe.cntThreads; + lppe->th32ParentProcessID = pe.th32ParentProcessID; + lppe->pcPriClassBase = pe.pcPriClassBase; + lppe->dwFlags = pe.dwFlags; + + WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0); + } + + return Ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->ProcessListCount > 0) + { + LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset); + + Snapshot->ProcessListIndex = 1; + RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W)); + Ret = TRUE; + } + else + { + + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe) +{ + PROCESSENTRY32W pe; + BOOL Ret; + + CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32)); + + pe.dwSize = sizeof(PROCESSENTRY32W); + + Ret = Process32NextW(hSnapshot, &pe); + if(Ret) + { + lppe->cntUsage = pe.cntUsage; + lppe->th32ProcessID = pe.th32ProcessID; + lppe->th32DefaultHeapID = pe.th32DefaultHeapID; + lppe->th32ModuleID = pe.th32ModuleID; + lppe->cntThreads = pe.cntThreads; + lppe->th32ParentProcessID = pe.th32ParentProcessID; + lppe->pcPriClassBase = pe.pcPriClassBase; + lppe->dwFlags = pe.dwFlags; + + WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0); + } + + return Ret; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->ProcessListCount > 0 && + Snapshot->ProcessListIndex < Snapshot->ProcessListCount) + { + LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset); + RtlCopyMemory(lppe, &Entries[Snapshot->ProcessListIndex++], sizeof(PROCESSENTRY32W)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->ThreadListCount > 0) + { + LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset); + Snapshot->ThreadListIndex = 1; + RtlCopyMemory(lpte, &Entries[0], sizeof(THREADENTRY32)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte) +{ + PTH32SNAPSHOT Snapshot; + LARGE_INTEGER SOffset; + SIZE_T ViewSize; + NTSTATUS Status; + + CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32)); + + SOffset.QuadPart = 0; + ViewSize = 0; + Snapshot = NULL; + + Status = NtMapViewOfSection(hSnapshot, + NtCurrentProcess(), + (PVOID*)&Snapshot, + 0, + 0, + &SOffset, + &ViewSize, + ViewShare, + 0, + PAGE_READWRITE); + if(NT_SUCCESS(Status)) + { + BOOL Ret; + + if(Snapshot->ThreadListCount > 0 && + Snapshot->ThreadListIndex < Snapshot->ThreadListCount) + { + LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset); + RtlCopyMemory(lpte, &Entries[Snapshot->ThreadListIndex++], sizeof(THREADENTRY32)); + Ret = TRUE; + } + else + { + SetLastError(ERROR_NO_MORE_FILES); + Ret = FALSE; + } + + NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); + return Ret; + } + + BaseSetLastNTError(Status); + return FALSE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +Toolhelp32ReadProcessMemory(DWORD th32ProcessID, LPCVOID lpBaseAddress, + LPVOID lpBuffer, SIZE_T cbRead, SIZE_T* lpNumberOfBytesRead) +{ + HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID); + if(hProcess != NULL) + { + BOOL Ret = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead); + CloseHandle(hProcess); + return Ret; + } + + return FALSE; +} + + +/* + * @implemented + */ +HANDLE +WINAPI +CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID) +{ + PRTL_DEBUG_INFORMATION HeapDebug, ModuleDebug; + PVOID ProcThrdInfo; + SIZE_T ProcThrdInfoSize; + NTSTATUS Status; + HANDLE hSnapShotSection = NULL; + + if(th32ProcessID == 0) + { + th32ProcessID = GetCurrentProcessId(); + } + + /* + * Get all information required for the snapshot + */ + Status = TH32CreateSnapshot(dwFlags, + th32ProcessID, + &HeapDebug, + &ModuleDebug, + &ProcThrdInfo, + &ProcThrdInfoSize); + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + /* + * Create a section handle and initialize the collected information + */ + Status = TH32CreateSnapshotSectionInitialize(dwFlags, + th32ProcessID, + HeapDebug, + ModuleDebug, + ProcThrdInfo, + &hSnapShotSection); + + /* + * Free the temporarily allocated memory which is no longer needed + */ + TH32FreeAllocatedResources(HeapDebug, + ModuleDebug, + ProcThrdInfo, + ProcThrdInfoSize); + + if(!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + return hSnapShotSection; +} + +/* EOF */ diff --git a/dll/win32/kernel32/client/utils.c b/dll/win32/kernel32/client/utils.c new file mode 100644 index 00000000000..db200fb635a --- /dev/null +++ b/dll/win32/kernel32/client/utils.c @@ -0,0 +1,563 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/utils.c + * PURPOSE: Utility and Support Functions + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * Pierre Schweitzer (pierre.schweitzer@reactos.org) + */ + +/* INCLUDES ****************************************************************/ + +#include +#ifdef _M_IX86 +#include "i386/ketypes.h" +#elif defined _M_AMD64 +#include "amd64/ketypes.h" +#endif + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +PRTL_CONVERT_STRING Basep8BitStringToUnicodeString; + +/* FUNCTIONS ****************************************************************/ + + +/* + * Converts an ANSI or OEM String to the TEB StaticUnicodeString + */ +PUNICODE_STRING +WINAPI +Basep8BitStringToStaticUnicodeString(IN LPCSTR String) +{ + PUNICODE_STRING StaticString = &(NtCurrentTeb()->StaticUnicodeString); + ANSI_STRING AnsiString; + NTSTATUS Status; + + /* Initialize an ANSI String */ + if (!NT_SUCCESS(RtlInitAnsiStringEx(&AnsiString, String))) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return NULL; + } + + /* Convert it */ + Status = Basep8BitStringToUnicodeString(StaticString, &AnsiString, FALSE); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + return StaticString; +} + +/* + * Allocates space from the Heap and converts an Unicode String into it + */ +BOOLEAN +WINAPI +Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, + IN LPCSTR String) +{ + ANSI_STRING AnsiString; + NTSTATUS Status; + + DPRINT("Basep8BitStringToDynamicUnicodeString\n"); + + /* Initialize an ANSI String */ + if (!NT_SUCCESS(RtlInitAnsiStringEx(&AnsiString, String))) + { + SetLastError(ERROR_BUFFER_OVERFLOW); + return FALSE; + } + + /* Convert it */ + Status = Basep8BitStringToUnicodeString(UnicodeString, &AnsiString, TRUE); + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + /* Return Status */ + return TRUE; +} + +/* + * Allocates space from the Heap and converts an Ansi String into it + */ +VOID +WINAPI +BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString, + OUT LPWSTR* UnicodeString) +{ + ANSI_STRING AnsiTemp; + UNICODE_STRING UnicodeTemp; + + DPRINT("BasepAnsiStringToHeapUnicodeString\n"); + + /* First create the ANSI_STRING */ + RtlInitAnsiString(&AnsiTemp, AnsiString); + + if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp, + &AnsiTemp, + TRUE))) + { + *UnicodeString = UnicodeTemp.Buffer; + } + else + { + *UnicodeString = NULL; + } +} + +PLARGE_INTEGER +WINAPI +BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout, + IN DWORD dwMilliseconds) +{ + /* Check if this is an infinite wait, which means no timeout argument */ + if (dwMilliseconds == INFINITE) return NULL; + + /* Otherwise, convert the time to NT Format */ + Timeout->QuadPart = UInt32x32To64(dwMilliseconds, -10000); + return Timeout; +} + +/* + * Converts lpSecurityAttributes + Object Name into ObjectAttributes. + */ +POBJECT_ATTRIBUTES +WINAPI +BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, + IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL, + IN PUNICODE_STRING ObjectName) +{ + ULONG Attributes = 0; + HANDLE RootDirectory = 0; + PVOID SecurityDescriptor = NULL; + BOOLEAN NeedOba = FALSE; + + DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n", + SecurityAttributes, ObjectName); + + /* Get the attributes if present */ + if (SecurityAttributes) + { + Attributes = SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0; + SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor; + NeedOba = TRUE; + } + + if (ObjectName) + { + Attributes |= OBJ_OPENIF; + RootDirectory = hBaseDir; + NeedOba = TRUE; + } + + DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n", + Attributes, RootDirectory, SecurityDescriptor); + + /* Create the Object Attributes */ + if (NeedOba) + { + InitializeObjectAttributes(ObjectAttributes, + ObjectName, + Attributes, + RootDirectory, + SecurityDescriptor); + return ObjectAttributes; + } + + /* Nothing to return */ + return NULL; +} + +/* + * Creates a stack for a thread or fiber + */ +NTSTATUS +WINAPI +BasepCreateStack(HANDLE hProcess, + SIZE_T StackReserve, + SIZE_T StackCommit, + PINITIAL_TEB InitialTeb) +{ + NTSTATUS Status; + SYSTEM_BASIC_INFORMATION SystemBasicInfo; + PIMAGE_NT_HEADERS Headers; + ULONG_PTR Stack = 0; + BOOLEAN UseGuard = FALSE; + + DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n", + hProcess, StackReserve, StackCommit); + + /* Get some memory information */ + Status = NtQuerySystemInformation(SystemBasicInformation, + &SystemBasicInfo, + sizeof(SYSTEM_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to query system info\n"); + return Status; + } + + /* Use the Image Settings if we are dealing with the current Process */ + if (hProcess == NtCurrentProcess()) + { + /* Get the Image Headers */ + Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); + + /* If we didn't get the parameters, find them ourselves */ + StackReserve = (StackReserve) ? + StackReserve : Headers->OptionalHeader.SizeOfStackReserve; + StackCommit = (StackCommit) ? + StackCommit : Headers->OptionalHeader.SizeOfStackCommit; + } + else + { + /* Use the System Settings if needed */ + StackReserve = (StackReserve) ? StackReserve : + SystemBasicInfo.AllocationGranularity; + StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize; + } + + /* Align everything to Page Size */ + StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity); + StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize); + #if 1 // FIXME: Remove once Guard Page support is here + StackCommit = StackReserve; + #endif + DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit); + + /* Reserve memory for the stack */ + Status = ZwAllocateVirtualMemory(hProcess, + (PVOID*)&Stack, + 0, + &StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to reserve stack\n"); + return Status; + } + + /* Now set up some basic Initial TEB Parameters */ + InitialTeb->AllocatedStackBase = (PVOID)Stack; + InitialTeb->StackBase = (PVOID)(Stack + StackReserve); + InitialTeb->PreviousStackBase = NULL; + InitialTeb->PreviousStackLimit = NULL; + + /* Update the Stack Position */ + Stack += StackReserve - StackCommit; + + /* Check if we will need a guard page */ + if (StackReserve > StackCommit) + { + Stack -= SystemBasicInfo.PageSize; + StackCommit += SystemBasicInfo.PageSize; + UseGuard = TRUE; + } + + /* Allocate memory for the stack */ + Status = ZwAllocateVirtualMemory(hProcess, + (PVOID*)&Stack, + 0, + &StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to allocate stack\n"); + return Status; + } + + /* Now set the current Stack Limit */ + InitialTeb->StackLimit = (PVOID)Stack; + + /* Create a guard page */ + if (UseGuard) + { + SIZE_T GuardPageSize = SystemBasicInfo.PageSize; + ULONG Dummy; + + /* Attempt maximum space possible */ + Status = ZwProtectVirtualMemory(hProcess, + (PVOID*)&Stack, + &GuardPageSize, + PAGE_GUARD | PAGE_READWRITE, + &Dummy); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to create guard page\n"); + return Status; + } + + /* Update the Stack Limit keeping in mind the Guard Page */ + InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - GuardPageSize); + } + + /* We are done! */ + return STATUS_SUCCESS; +} + +VOID +WINAPI +BasepFreeStack(HANDLE hProcess, + PINITIAL_TEB InitialTeb) +{ + SIZE_T Dummy = 0; + + /* Free the Stack */ + NtFreeVirtualMemory(hProcess, + &InitialTeb->AllocatedStackBase, + &Dummy, + MEM_RELEASE); +} + +/* + * Creates the Initial Context for a Thread or Fiber + */ +VOID +WINAPI +BasepInitializeContext(IN PCONTEXT Context, + IN PVOID Parameter, + IN PVOID StartAddress, + IN PVOID StackAddress, + IN ULONG ContextType) +{ +#ifdef _M_IX86 + ULONG ContextFlags; + DPRINT("BasepInitializeContext: %p\n", Context); + + /* Setup the Initial Win32 Thread Context */ + Context->Eax = (ULONG)StartAddress; + Context->Ebx = (ULONG)Parameter; + Context->Esp = (ULONG)StackAddress; + /* The other registers are undefined */ + + /* Setup the Segments */ + Context->SegFs = KGDT_R3_TEB | RPL_MASK; + Context->SegEs = KGDT_R3_DATA | RPL_MASK; + Context->SegDs = KGDT_R3_DATA | RPL_MASK; + Context->SegCs = KGDT_R3_CODE | RPL_MASK; + Context->SegSs = KGDT_R3_DATA | RPL_MASK; + Context->SegGs = 0; + + /* Set the Context Flags */ + ContextFlags = Context->ContextFlags; + Context->ContextFlags = CONTEXT_FULL; + + /* Give it some room for the Parameter */ + Context->Esp -= sizeof(PVOID); + + /* Set the EFLAGS */ + Context->EFlags = 0x3000; /* IOPL 3 */ + + /* What kind of context is being created? */ + if (ContextType == 1) + { + /* For Threads */ + Context->Eip = (ULONG)BaseThreadStartupThunk; + } + else if (ContextType == 2) + { + /* This is a fiber: make space for the return address */ + Context->Esp -= sizeof(PVOID); + *((PVOID*)Context->Esp) = BaseFiberStartup; + + /* Is FPU state required? */ + Context->ContextFlags |= ContextFlags; + if (ContextFlags == CONTEXT_FLOATING_POINT) + { + /* Set an initial state */ + Context->FloatSave.ControlWord = 0x27F; + Context->FloatSave.StatusWord = 0; + Context->FloatSave.TagWord = 0xFFFF; + Context->FloatSave.ErrorOffset = 0; + Context->FloatSave.ErrorSelector = 0; + Context->FloatSave.DataOffset = 0; + Context->FloatSave.DataSelector = 0; + if (SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE]) + Context->Dr6 = 0x1F80; + } + } + else + { + /* For first thread in a Process */ + Context->Eip = (ULONG)BaseProcessStartThunk; + } + +#elif defined(_M_AMD64) + DPRINT("BasepInitializeContext: %p\n", Context); + + /* Setup the Initial Win32 Thread Context */ + Context->Rax = (ULONG_PTR)StartAddress; + Context->Rbx = (ULONG_PTR)Parameter; + Context->Rsp = (ULONG_PTR)StackAddress; + /* The other registers are undefined */ + + /* Setup the Segments */ + Context->SegGs = KGDT64_R3_DATA | RPL_MASK; + Context->SegEs = KGDT64_R3_DATA | RPL_MASK; + Context->SegDs = KGDT64_R3_DATA | RPL_MASK; + Context->SegCs = KGDT64_R3_CODE | RPL_MASK; + Context->SegSs = KGDT64_R3_DATA | RPL_MASK; + Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK; + + /* Set the EFLAGS */ + Context->EFlags = 0x3000; /* IOPL 3 */ + + if (ContextType == 1) /* For Threads */ + { + Context->Rip = (ULONG_PTR)BaseThreadStartupThunk; + } + else if (ContextType == 2) /* For Fibers */ + { + Context->Rip = (ULONG_PTR)BaseFiberStartup; + } + else /* For first thread in a Process */ + { + Context->Rip = (ULONG_PTR)BaseProcessStartThunk; + } + + /* Set the Context Flags */ + Context->ContextFlags = CONTEXT_FULL; + + /* Give it some room for the Parameter */ + Context->Rsp -= sizeof(PVOID); +#else +#warning Unknown architecture + UNIMPLEMENTED; + DbgBreakPoint(); +#endif +} + +/* + * Checks if the privilege for Real-Time Priority is there + */ +BOOLEAN +WINAPI +BasepCheckRealTimePrivilege(VOID) +{ + return TRUE; +} + +/* + * Maps an image file into a section + */ +NTSTATUS +WINAPI +BasepMapFile(IN LPCWSTR lpApplicationName, + OUT PHANDLE hSection, + IN PUNICODE_STRING ApplicationName) +{ + RTL_RELATIVE_NAME_U RelativeName; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE hFile = NULL; + IO_STATUS_BLOCK IoStatusBlock; + + DPRINT("BasepMapFile\n"); + + /* Zero out the Relative Directory */ + RelativeName.ContainingDirectory = NULL; + + /* Find the application name */ + if (!RtlDosPathNameToNtPathName_U(lpApplicationName, + ApplicationName, + NULL, + &RelativeName)) + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + DPRINT("ApplicationName %wZ\n", ApplicationName); + DPRINT("RelativeName %wZ\n", &RelativeName.RelativeName); + + /* Did we get a relative name? */ + if (RelativeName.RelativeName.Length) + { + ApplicationName = &RelativeName.RelativeName; + } + + /* Initialize the Object Attributes */ + InitializeObjectAttributes(&ObjectAttributes, + ApplicationName, + OBJ_CASE_INSENSITIVE, + RelativeName.ContainingDirectory, + NULL); + + /* Try to open the executable */ + Status = NtOpenFile(&hFile, + SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open file\n"); + BaseSetLastNTError(Status); + return Status; + } + + /* Create a section for this file */ + Status = NtCreateSection(hSection, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_EXECUTE, + SEC_IMAGE, + hFile); + NtClose(hFile); + + /* Return status */ + DPRINT("Section: %lx for file: %lx\n", *hSection, hFile); + return Status; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +BaseCheckRunApp(IN DWORD Unknown1, + IN DWORD Unknown2, + IN DWORD Unknown3, + IN DWORD Unknown4, + IN DWORD Unknown5, + IN DWORD Unknown6, + IN DWORD Unknown7, + IN DWORD Unknown8, + IN DWORD Unknown9, + IN DWORD Unknown10) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +BasepCheckWinSaferRestrictions(IN DWORD Unknown1, + IN DWORD Unknown2, + IN DWORD Unknown3, + IN DWORD Unknown4, + IN DWORD Unknown5, + IN DWORD Unknown6) +{ + STUB; + return FALSE; +} diff --git a/dll/win32/kernel32/client/vdm.c b/dll/win32/kernel32/client/vdm.c new file mode 100644 index 00000000000..7ed8780fd09 --- /dev/null +++ b/dll/win32/kernel32/client/vdm.c @@ -0,0 +1,169 @@ +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/kernel32/client/vdm.c + * PURPOSE: Virtual Dos Machine (VDM) Support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include + +#define NDEBUG +#include + +/* TYPES **********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* + * @unimplemented + */ +BOOL +WINAPI +CmdBatNotification ( + DWORD Unknown + ) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +DWORD +WINAPI +ExitVDM ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + STUB; + return 0; +} + + +/* + * @unimplemented + */ +DWORD +WINAPI +GetNextVDMCommand ( + DWORD Unknown0 + ) +{ + STUB; + return 0; +} + + +/* + * @unimplemented + */ +DWORD +WINAPI +GetVDMCurrentDirectories ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + STUB; + return 0; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +RegisterConsoleVDM ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10 + ) +{ + STUB; + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +RegisterWowBaseHandlers ( + DWORD Unknown0 + ) +{ + STUB; + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +RegisterWowExec ( + DWORD Unknown0 + ) +{ + STUB; + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +SetVDMCurrentDirectories ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +DWORD +WINAPI +VDMConsoleOperation ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + STUB; + return 0; +} + + +/* + * @unimplemented + */ +DWORD +WINAPI +VDMOperationStarted ( + DWORD Unknown0 + ) +{ + STUB; + return 0; +} diff --git a/dll/win32/kernel32/client/version.c b/dll/win32/kernel32/client/version.c new file mode 100644 index 00000000000..f1757af64eb --- /dev/null +++ b/dll/win32/kernel32/client/version.c @@ -0,0 +1,223 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/version.c + * PURPOSE: Version functions + * PROGRAMMER: Ariadne (ariadne@xs4all.nl) + Ged Murphy (gedmurphy@reactos.org) + */ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +SetRosSpecificInfo(IN LPOSVERSIONINFOEXW VersionInformation) +{ + CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)]; + PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer; + OBJECT_ATTRIBUTES ObjectAttributes; + DWORD ReportAsWorkstation = 0; + HANDLE hKey; + DWORD dwSize; + NTSTATUS Status; + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version"); + UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation"); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_OPENIF | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Don't change anything if the key doesn't exist */ + Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + /* Get the value from the registry and make sure it's a 32-bit value */ + Status = NtQueryValueKey(hKey, + &ValName, + KeyValuePartialInformation, + kvpInfo, + sizeof(Buffer), + &dwSize); + if ((NT_SUCCESS(Status)) && + (kvpInfo->Type == REG_DWORD) && + (kvpInfo->DataLength == sizeof(DWORD))) + { + /* Is the value set? */ + ReportAsWorkstation = *(PULONG)kvpInfo->Data; + if ((VersionInformation->wProductType == VER_NT_SERVER) && + (ReportAsWorkstation)) + { + /* It is, modify the product type to report a workstation */ + VersionInformation->wProductType = VER_NT_WORKSTATION; + DPRINT1("We modified the reported OS from NtProductServer to NtProductWinNt\n"); + } + } + + /* Close the handle */ + NtClose(hKey); + } +} + +/* + * @implemented + */ +DWORD +WINAPI +GetVersion(VOID) +{ + PPEB Peb = NtCurrentPeb(); + DWORD Result; + + Result = MAKELONG(MAKEWORD(Peb->OSMajorVersion, Peb->OSMinorVersion), + (Peb->OSPlatformId ^ 2) << 14); + Result |= LOWORD(Peb->OSBuildNumber) << 16; + return Result; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetVersionExW(IN LPOSVERSIONINFOW lpVersionInformation) +{ + NTSTATUS Status; + LPOSVERSIONINFOEXW lpVersionInformationEx; + + if ((lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW)) && + (lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW))) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + Status = RtlGetVersion((PRTL_OSVERSIONINFOW)lpVersionInformation); + if (Status == STATUS_SUCCESS) + { + if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW)) + { + lpVersionInformationEx = (PVOID)lpVersionInformation; + lpVersionInformationEx->wReserved = 0; + + /* ReactOS specific changes */ + SetRosSpecificInfo(lpVersionInformationEx); + } + + return TRUE; + } + + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetVersionExA(IN LPOSVERSIONINFOA lpVersionInformation) +{ + OSVERSIONINFOEXW VersionInformation; + LPOSVERSIONINFOEXA lpVersionInformationEx; + UNICODE_STRING CsdVersionW; + NTSTATUS Status; + ANSI_STRING CsdVersionA; + + if ((lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA)) && + (lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA))) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + + if (!GetVersionExW((LPOSVERSIONINFOW)&VersionInformation)) return FALSE; + + /* Copy back fields that match both supported structures */ + lpVersionInformation->dwMajorVersion = VersionInformation.dwMajorVersion; + lpVersionInformation->dwMinorVersion = VersionInformation.dwMinorVersion; + lpVersionInformation->dwBuildNumber = VersionInformation.dwBuildNumber; + lpVersionInformation->dwPlatformId = VersionInformation.dwPlatformId; + + if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA)) + { + lpVersionInformationEx = (PVOID)lpVersionInformation; + lpVersionInformationEx->wServicePackMajor = VersionInformation.wServicePackMajor; + lpVersionInformationEx->wServicePackMinor = VersionInformation.wServicePackMinor; + lpVersionInformationEx->wSuiteMask = VersionInformation.wSuiteMask; + lpVersionInformationEx->wProductType = VersionInformation.wProductType; + lpVersionInformationEx->wReserved = VersionInformation.wReserved; + } + + /* Convert the CSD string */ + RtlInitEmptyAnsiString(&CsdVersionA, + lpVersionInformation->szCSDVersion, + sizeof(lpVersionInformation->szCSDVersion)); + RtlInitUnicodeString(&CsdVersionW, VersionInformation.szCSDVersion); + Status = RtlUnicodeStringToAnsiString(&CsdVersionA, &CsdVersionW, FALSE); + return (NT_SUCCESS(Status)); +} + +/* + * @implemented + */ +BOOL +WINAPI +VerifyVersionInfoW(IN LPOSVERSIONINFOEXW lpVersionInformation, + IN DWORD dwTypeMask, + IN DWORDLONG dwlConditionMask) +{ + NTSTATUS Status; + + Status = RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW)lpVersionInformation, + dwTypeMask, + dwlConditionMask); + switch (Status) + { + case STATUS_INVALID_PARAMETER: + SetLastError(ERROR_BAD_ARGUMENTS); + return FALSE; + + case STATUS_REVISION_MISMATCH: + DPRINT1("ReactOS returning version mismatch. Investigate!\n"); + SetLastError(ERROR_OLD_WIN_VERSION); + return FALSE; + + default: + /* RtlVerifyVersionInfo shouldn't report any other failure code! */ + ASSERT(NT_SUCCESS(Status)); + return TRUE; + } +} + +/* + * @implemented + */ +BOOL +WINAPI +VerifyVersionInfoA(IN LPOSVERSIONINFOEXA lpVersionInformation, + IN DWORD dwTypeMask, + IN DWORDLONG dwlConditionMask) +{ + OSVERSIONINFOEXW viex; + + /* NOTE: szCSDVersion is ignored, we don't need to convert it to Unicode */ + viex.dwOSVersionInfoSize = sizeof(viex); + viex.dwMajorVersion = lpVersionInformation->dwMajorVersion; + viex.dwMinorVersion = lpVersionInformation->dwMinorVersion; + viex.dwBuildNumber = lpVersionInformation->dwBuildNumber; + viex.dwPlatformId = lpVersionInformation->dwPlatformId; + viex.wServicePackMajor = lpVersionInformation->wServicePackMajor; + viex.wServicePackMinor = lpVersionInformation->wServicePackMinor; + viex.wSuiteMask = lpVersionInformation->wSuiteMask; + viex.wProductType = lpVersionInformation->wProductType; + viex.wReserved = lpVersionInformation->wReserved; + return VerifyVersionInfoW(&viex, dwTypeMask, dwlConditionMask); +} diff --git a/dll/win32/kernel32/mem/virtual.c b/dll/win32/kernel32/client/virtmem.c similarity index 71% rename from dll/win32/kernel32/mem/virtual.c rename to dll/win32/kernel32/client/virtmem.c index 5ccc3dff170..73ce2755d45 100644 --- a/dll/win32/kernel32/mem/virtual.c +++ b/dll/win32/kernel32/client/virtmem.c @@ -1,19 +1,19 @@ /* * PROJECT: ReactOS Win32 Base API * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/mem/virtual.c + * FILE: dll/win32/kernel32/client/virtmem.c * PURPOSE: Handles virtual memory APIs * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ +/* FUNCTIONS ******************************************************************/ /* * @implemented @@ -27,18 +27,38 @@ VirtualAllocEx(IN HANDLE hProcess, IN DWORD flProtect) { NTSTATUS Status; - - /* Allocate the memory */ - Status = NtAllocateVirtualMemory(hProcess, - (PVOID *)&lpAddress, - 0, - &dwSize, - flAllocationType, - flProtect); + + /* Make sure the address is within the granularity of the system (64K) */ + if ((lpAddress) && + (lpAddress < (PVOID)BaseStaticServerData->SysInfo.AllocationGranularity)) + { + /* Fail the call */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* Handle any possible exceptions */ + _SEH2_TRY + { + /* Allocate the memory */ + Status = NtAllocateVirtualMemory(hProcess, + &lpAddress, + 0, + &dwSize, + flAllocationType, + flProtect); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + /* Check for status */ if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return NULL; } @@ -76,17 +96,18 @@ VirtualFreeEx(IN HANDLE hProcess, { NTSTATUS Status; - if (dwSize == 0 || !(dwFreeType & MEM_RELEASE)) + /* Validate size and flags */ + if (!(dwSize) || !(dwFreeType & MEM_RELEASE)) { /* Free the memory */ Status = NtFreeVirtualMemory(hProcess, - (PVOID *)&lpAddress, - (PULONG)&dwSize, + &lpAddress, + &dwSize, dwFreeType); if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -94,7 +115,8 @@ VirtualFreeEx(IN HANDLE hProcess, return TRUE; } - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + /* Invalid combo */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } @@ -154,7 +176,7 @@ VirtualProtectEx(IN HANDLE hProcess, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -182,7 +204,7 @@ VirtualLock(IN LPVOID lpAddress, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -229,7 +251,7 @@ VirtualQueryEx(IN HANDLE hProcess, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return 0; } @@ -257,7 +279,7 @@ VirtualUnlock(IN LPVOID lpAddress, if (!NT_SUCCESS(Status)) { /* We failed */ - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -270,14 +292,12 @@ VirtualUnlock(IN LPVOID lpAddress, */ UINT WINAPI -GetWriteWatch( - DWORD dwFlags, - PVOID lpBaseAddress, - SIZE_T dwRegionSize, - PVOID *lpAddresses, - PULONG_PTR lpdwCount, - PULONG lpdwGranularity - ) +GetWriteWatch(IN DWORD dwFlags, + IN PVOID lpBaseAddress, + IN SIZE_T dwRegionSize, + IN PVOID *lpAddresses, + OUT PULONG_PTR lpdwCount, + OUT PULONG lpdwGranularity) { NTSTATUS Status; @@ -288,10 +308,9 @@ GetWriteWatch( lpAddresses, lpdwCount, lpdwGranularity); - if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -303,20 +322,17 @@ GetWriteWatch( */ UINT WINAPI -ResetWriteWatch( - LPVOID lpBaseAddress, - SIZE_T dwRegionSize - ) +ResetWriteWatch(IN LPVOID lpBaseAddress, + IN SIZE_T dwRegionSize) { NTSTATUS Status; Status = NtResetWriteWatch(NtCurrentProcess(), lpBaseAddress, dwRegionSize); - if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return -1; } @@ -328,21 +344,16 @@ ResetWriteWatch( */ BOOL WINAPI -AllocateUserPhysicalPages( - HANDLE hProcess, - PULONG_PTR NumberOfPages, - PULONG_PTR UserPfnArray - ) +AllocateUserPhysicalPages(IN HANDLE hProcess, + IN PULONG_PTR NumberOfPages, + OUT PULONG_PTR UserPfnArray) { NTSTATUS Status; - Status = NtAllocateUserPhysicalPages(hProcess, - NumberOfPages, - UserPfnArray); - + Status = NtAllocateUserPhysicalPages(hProcess, NumberOfPages, UserPfnArray); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -354,21 +365,16 @@ AllocateUserPhysicalPages( */ BOOL WINAPI -FreeUserPhysicalPages( - HANDLE hProcess, - PULONG_PTR NumberOfPages, - PULONG_PTR PageArray - ) +FreeUserPhysicalPages(IN HANDLE hProcess, + IN PULONG_PTR NumberOfPages, + IN PULONG_PTR PageArray) { NTSTATUS Status; - Status = NtFreeUserPhysicalPages(hProcess, - NumberOfPages, - PageArray); - + Status = NtFreeUserPhysicalPages(hProcess, NumberOfPages, PageArray); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -380,21 +386,16 @@ FreeUserPhysicalPages( */ BOOL WINAPI -MapUserPhysicalPages( - PVOID VirtualAddress, - ULONG_PTR NumberOfPages, - PULONG_PTR PageArray OPTIONAL - ) +MapUserPhysicalPages(IN PVOID VirtualAddress, + IN ULONG_PTR NumberOfPages, + OUT PULONG_PTR PageArray OPTIONAL) { NTSTATUS Status; - Status = NtMapUserPhysicalPages(VirtualAddress, - NumberOfPages, - PageArray); - + Status = NtMapUserPhysicalPages(VirtualAddress, NumberOfPages, PageArray); if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } @@ -406,21 +407,18 @@ MapUserPhysicalPages( */ BOOL WINAPI -MapUserPhysicalPagesScatter( - PVOID *VirtualAddresses, - ULONG_PTR NumberOfPages, - PULONG_PTR PageArray OPTIONAL - ) +MapUserPhysicalPagesScatter(IN PVOID *VirtualAddresses, + IN ULONG_PTR NumberOfPages, + OUT PULONG_PTR PageArray OPTIONAL) { NTSTATUS Status; Status = NtMapUserPhysicalPagesScatter(VirtualAddresses, NumberOfPages, PageArray); - if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + BaseSetLastNTError(Status); return FALSE; } diff --git a/dll/win32/kernel32/client/vista.c b/dll/win32/kernel32/client/vista.c new file mode 100644 index 00000000000..aff5208f1a3 --- /dev/null +++ b/dll/win32/kernel32/client/vista.c @@ -0,0 +1,870 @@ +/* COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: Vista functions + * PROGRAMMER: Thomas Weidenmueller + */ + +#include + +#define NDEBUG +#include + +#if _WIN32_WINNT >= 0x600 + +/* FIXME: Move these RTL declarations to the NDK */ +NTSTATUS +NTAPI +RtlSleepConditionVariableCS(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, + IN OUT PRTL_CRITICAL_SECTION CriticalSection, + IN PLARGE_INTEGER TimeOut OPTIONAL); + +NTSTATUS +NTAPI +RtlSleepConditionVariableSRW(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, + IN OUT PRTL_SRWLOCK SRWLock, + IN PLARGE_INTEGER TimeOut OPTIONAL, + IN ULONG Flags); + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +BOOL +WINAPI +SleepConditionVariableCS(IN OUT PCONDITION_VARIABLE ConditionVariable, + IN OUT PCRITICAL_SECTION CriticalSection, + IN DWORD dwMilliseconds) +{ + NTSTATUS Status = 0; + LARGE_INTEGER TimeOut; + PLARGE_INTEGER TimeOutPtr = NULL; + + if (dwMilliseconds != INFINITE) + { + TimeOut.QuadPart = UInt32x32To64(-10000, dwMilliseconds); + TimeOutPtr = &TimeOut; + } + +#if 0 + Status = RtlSleepConditionVariableCS((PRTL_CONDITION_VARIABLE)ConditionVariable, + (PRTL_CRITICAL_SECTION)CriticalSection, + TimeOutPtr); +#endif + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SleepConditionVariableSRW(IN OUT PCONDITION_VARIABLE ConditionVariable, + IN OUT PSRWLOCK SRWLock, + IN DWORD dwMilliseconds, + IN ULONG Flags) +{ + NTSTATUS Status = 0; + LARGE_INTEGER TimeOut; + PLARGE_INTEGER TimeOutPtr = NULL; + + if (dwMilliseconds != INFINITE) + { + TimeOut.QuadPart = UInt32x32To64(-10000, dwMilliseconds); + TimeOutPtr = &TimeOut; + } + +#if 0 + Status = RtlSleepConditionVariableSRW((PRTL_CONDITION_VARIABLE)ConditionVariable, + (PRTL_SRWLOCK)SRWLock, + TimeOutPtr, + Flags); +#endif + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, + IN DWORD dwSpinCount, + IN DWORD flags ) +{ + NTSTATUS Status; + + /* FIXME: Flags ignored */ + + /* Initialize the critical section */ + Status = RtlInitializeCriticalSectionAndSpinCount( + (PRTL_CRITICAL_SECTION)lpCriticalSection, + dwSpinCount); + if (!NT_SUCCESS(Status)) + { + /* Set failure code */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} + + + +/* + * @implemented + */ +BOOL +WINAPI +QueryFullProcessImageNameW(HANDLE hProcess, + DWORD dwFlags, + LPWSTR lpExeName, + PDWORD pdwSize) +{ + BYTE Buffer[sizeof(UNICODE_STRING) + MAX_PATH * sizeof(WCHAR)]; + UNICODE_STRING *DynamicBuffer = NULL; + UNICODE_STRING *Result = NULL; + NTSTATUS Status; + DWORD Needed; + + Status = NtQueryInformationProcess(hProcess, + ProcessImageFileName, + Buffer, + sizeof(Buffer) - sizeof(WCHAR), + &Needed); + if (Status == STATUS_INFO_LENGTH_MISMATCH) + { + DynamicBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Needed + sizeof(WCHAR)); + if (!DynamicBuffer) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return FALSE; + } + + Status = NtQueryInformationProcess(hProcess, + ProcessImageFileName, + (LPBYTE)DynamicBuffer, + Needed, + &Needed); + Result = DynamicBuffer; + } + else Result = (PUNICODE_STRING)Buffer; + + if (!NT_SUCCESS(Status)) goto Cleanup; + + if (Result->Length / sizeof(WCHAR) + 1 > *pdwSize) + { + Status = STATUS_BUFFER_TOO_SMALL; + goto Cleanup; + } + + *pdwSize = Result->Length / sizeof(WCHAR); + memcpy(lpExeName, Result->Buffer, Result->Length); + lpExeName[*pdwSize] = 0; + +Cleanup: + RtlFreeHeap(RtlGetProcessHeap(), 0, DynamicBuffer); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + } + + return !Status; +} + + +/* + * @implemented + */ +BOOL +WINAPI +QueryFullProcessImageNameA(HANDLE hProcess, + DWORD dwFlags, + LPSTR lpExeName, + PDWORD pdwSize) +{ + DWORD pdwSizeW = *pdwSize; + BOOL Result; + LPWSTR lpExeNameW; + + lpExeNameW = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + *pdwSize * sizeof(WCHAR)); + if (!lpExeNameW) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return FALSE; + } + + Result = QueryFullProcessImageNameW(hProcess, dwFlags, lpExeNameW, &pdwSizeW); + + if (Result) + Result = (0 != WideCharToMultiByte(CP_ACP, 0, + lpExeNameW, + -1, + lpExeName, + *pdwSize, + NULL, NULL)); + + if (Result) + *pdwSize = strlen(lpExeName); + + RtlFreeHeap(RtlGetProcessHeap(), 0, lpExeNameW); + return Result; +} + +/* + * @unimplemented + */ +HRESULT +WINAPI +GetApplicationRecoveryCallback(IN HANDLE hProcess, + OUT APPLICATION_RECOVERY_CALLBACK* pRecoveryCallback, + OUT PVOID* ppvParameter, + PDWORD dwPingInterval, + PDWORD dwFlags) +{ + UNIMPLEMENTED; + return E_FAIL; +} + + +/* + * @unimplemented + */ +HRESULT +WINAPI +GetApplicationRestart(IN HANDLE hProcess, + OUT PWSTR pwzCommandline OPTIONAL, + IN OUT PDWORD pcchSize, + OUT PDWORD pdwFlags OPTIONAL) +{ + UNIMPLEMENTED; + return E_FAIL; +} + + +/* + * @unimplemented + */ +VOID +WINAPI +RecoveryFinished(IN BOOL bSuccess) +{ + UNIMPLEMENTED; +} + + +/* + * @unimplemented + */ +HRESULT +WINAPI +RecoveryInProgress(OUT PBOOL pbCancelled) +{ + UNIMPLEMENTED; + return E_FAIL; +} + + +/* + * @unimplemented + */ +HRESULT +WINAPI +RegisterApplicationRecoveryCallback(IN APPLICATION_RECOVERY_CALLBACK pRecoveyCallback, + IN PVOID pvParameter OPTIONAL, + DWORD dwPingInterval, + DWORD dwFlags) +{ + UNIMPLEMENTED; + return E_FAIL; +} + + +/* + * @unimplemented + */ +HRESULT +WINAPI +RegisterApplicationRestart(IN PCWSTR pwzCommandline OPTIONAL, + IN DWORD dwFlags) +{ + UNIMPLEMENTED; + return E_FAIL; +} + +/*-------------------------------------------------------------- + * GetConsoleHistoryInfo + * + * @implemented + */ +BOOL +WINAPI +GetConsoleHistoryInfo(PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest = MAKE_CSR_API(GET_HISTORY_INFO, CSR_CONSOLE); + NTSTATUS Status; + if (lpConsoleHistoryInfo->cbSize != sizeof(CONSOLE_HISTORY_INFO)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + lpConsoleHistoryInfo->HistoryBufferSize = Request.Data.GetHistoryInfo.HistoryBufferSize; + lpConsoleHistoryInfo->NumberOfHistoryBuffers = Request.Data.GetHistoryInfo.NumberOfHistoryBuffers; + lpConsoleHistoryInfo->dwFlags = Request.Data.GetHistoryInfo.dwFlags; + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleHistoryInfo + * + * @implemented + */ +BOOL +WINAPI +SetConsoleHistoryInfo(IN PCONSOLE_HISTORY_INFO lpConsoleHistoryInfo) +{ + CSR_API_MESSAGE Request; + ULONG CsrRequest = MAKE_CSR_API(GET_HISTORY_INFO, CSR_CONSOLE); + NTSTATUS Status; + if (lpConsoleHistoryInfo->cbSize != sizeof(CONSOLE_HISTORY_INFO)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + Request.Data.SetHistoryInfo.HistoryBufferSize = lpConsoleHistoryInfo->HistoryBufferSize; + Request.Data.SetHistoryInfo.NumberOfHistoryBuffers = lpConsoleHistoryInfo->NumberOfHistoryBuffers; + Request.Data.SetHistoryInfo.dwFlags = lpConsoleHistoryInfo->dwFlags; + Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetConsoleOriginalTitleW + * + * @unimplemented + */ +DWORD +WINAPI +GetConsoleOriginalTitleW(OUT LPWSTR lpConsoleTitle, + IN DWORD nSize) +{ + DPRINT1("GetConsoleOriginalTitleW(0x%p, 0x%x) UNIMPLEMENTED!\n", lpConsoleTitle, nSize); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/*-------------------------------------------------------------- + * GetConsoleOriginalTitleA + * + * @unimplemented + */ +DWORD +WINAPI +GetConsoleOriginalTitleA(OUT LPSTR lpConsoleTitle, + IN DWORD nSize) +{ + DPRINT1("GetConsoleOriginalTitleA(0x%p, 0x%x) UNIMPLEMENTED!\n", lpConsoleTitle, nSize); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/*-------------------------------------------------------------- + * GetConsoleScreenBufferInfoEx + * + * @unimplemented + */ +BOOL +WINAPI +GetConsoleScreenBufferInfoEx(IN HANDLE hConsoleOutput, + OUT PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx) +{ + DPRINT1("GetConsoleScreenBufferInfoEx(0x%p, 0x%p) UNIMPLEMENTED!\n", hConsoleOutput, lpConsoleScreenBufferInfoEx); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/*-------------------------------------------------------------- + * SetConsoleScreenBufferInfoEx + * + * @unimplemented + */ +BOOL +WINAPI +SetConsoleScreenBufferInfoEx(IN HANDLE hConsoleOutput, + IN PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx) +{ + DPRINT1("SetConsoleScreenBufferInfoEx(0x%p, 0x%p) UNIMPLEMENTED!\n", hConsoleOutput, lpConsoleScreenBufferInfoEx); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/*-------------------------------------------------------------- + * GetCurrentConsoleFontEx + * + * @unimplemented + */ +BOOL +WINAPI +GetCurrentConsoleFontEx(IN HANDLE hConsoleOutput, + IN BOOL bMaximumWindow, + OUT PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx) +{ + DPRINT1("GetCurrentConsoleFontEx(0x%p, 0x%x, 0x%p) UNIMPLEMENTED!\n", hConsoleOutput, bMaximumWindow, lpConsoleCurrentFontEx); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* + * @implemented + */ +BOOLEAN +WINAPI +CreateSymbolicLinkW(IN LPCWSTR lpSymlinkFileName, + IN LPCWSTR lpTargetFileName, + IN DWORD dwFlags) +{ + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hSymlink = NULL; + UNICODE_STRING SymlinkFileName = { 0, 0, NULL }; + UNICODE_STRING TargetFileName = { 0, 0, NULL }; + BOOLEAN bAllocatedTarget = FALSE, bRelativePath = FALSE; + LPWSTR lpTargetFullFileName = NULL; + SIZE_T cbPrintName; + SIZE_T cbReparseData; + PREPARSE_DATA_BUFFER pReparseData = NULL; + PBYTE pBufTail; + NTSTATUS Status; + ULONG dwCreateOptions; + DWORD dwErr; + + if(!lpSymlinkFileName || !lpTargetFileName || (dwFlags | SYMBOLIC_LINK_FLAG_DIRECTORY) != SYMBOLIC_LINK_FLAG_DIRECTORY) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(dwFlags & SYMBOLIC_LINK_FLAG_DIRECTORY) + dwCreateOptions = FILE_DIRECTORY_FILE; + else + dwCreateOptions = FILE_NON_DIRECTORY_FILE; + + switch(RtlDetermineDosPathNameType_U(lpTargetFileName)) + { + case RtlPathTypeUnknown: + case RtlPathTypeRooted: + case RtlPathTypeRelative: + bRelativePath = TRUE; + RtlInitUnicodeString(&TargetFileName, lpTargetFileName); + break; + + case RtlPathTypeDriveRelative: + { + LPWSTR FilePart; + SIZE_T cchTargetFullFileName; + + cchTargetFullFileName = GetFullPathNameW(lpTargetFileName, 0, NULL, &FilePart); + + if(cchTargetFullFileName == 0) + { + dwErr = GetLastError(); + goto Cleanup; + } + + lpTargetFullFileName = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchTargetFullFileName * sizeof(WCHAR)); + + if(lpTargetFullFileName == NULL) + { + dwErr = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + if(GetFullPathNameW(lpTargetFileName, cchTargetFullFileName, lpTargetFullFileName, &FilePart) == 0) + { + dwErr = GetLastError(); + goto Cleanup; + } + } + + lpTargetFileName = lpTargetFullFileName; + + // fallthrough + + case RtlPathTypeUncAbsolute: + case RtlPathTypeDriveAbsolute: + case RtlPathTypeLocalDevice: + case RtlPathTypeRootLocalDevice: + default: + if(!RtlDosPathNameToNtPathName_U(lpTargetFileName, &TargetFileName, NULL, NULL)) + { + bAllocatedTarget = TRUE; + dwErr = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + } + + cbPrintName = wcslen(lpTargetFileName) * sizeof(WCHAR); + cbReparseData = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + TargetFileName.Length + cbPrintName; + pReparseData = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbReparseData); + + if(pReparseData == NULL) + { + dwErr = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + pBufTail = (PBYTE)(pReparseData->SymbolicLinkReparseBuffer.PathBuffer); + + pReparseData->ReparseTag = (ULONG)IO_REPARSE_TAG_SYMLINK; + pReparseData->ReparseDataLength = (USHORT)cbReparseData - REPARSE_DATA_BUFFER_HEADER_SIZE; + pReparseData->Reserved = 0; + + pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; + pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength = TargetFileName.Length; + pBufTail += pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset; + RtlCopyMemory(pBufTail, TargetFileName.Buffer, TargetFileName.Length); + + pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset = pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength; + pReparseData->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)cbPrintName; + pBufTail += pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset; + RtlCopyMemory(pBufTail, lpTargetFileName, cbPrintName); + + pReparseData->SymbolicLinkReparseBuffer.Flags = 0; + + if(bRelativePath) + pReparseData->SymbolicLinkReparseBuffer.Flags |= 1; // TODO! give this lone flag a name + + if(!RtlDosPathNameToNtPathName_U(lpSymlinkFileName, &SymlinkFileName, NULL, NULL)) + { + dwErr = ERROR_PATH_NOT_FOUND; + goto Cleanup; + } + + InitializeObjectAttributes(&ObjectAttributes, &SymlinkFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); + + Status = NtCreateFile + ( + &hSymlink, + FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_CREATE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | dwCreateOptions, + NULL, + 0 + ); + + if(!NT_SUCCESS(Status)) + { + dwErr = RtlNtStatusToDosError(Status); + goto Cleanup; + } + + Status = NtFsControlFile + ( + hSymlink, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_SET_REPARSE_POINT, + pReparseData, + cbReparseData, + NULL, + 0 + ); + + if(!NT_SUCCESS(Status)) + { + FILE_DISPOSITION_INFORMATION DispInfo; + DispInfo.DeleteFile = TRUE; + NtSetInformationFile(hSymlink, &IoStatusBlock, &DispInfo, sizeof(DispInfo), FileDispositionInformation); + + dwErr = RtlNtStatusToDosError(Status); + goto Cleanup; + } + + dwErr = NO_ERROR; + +Cleanup: + if(hSymlink) + NtClose(hSymlink); + + RtlFreeUnicodeString(&SymlinkFileName); + if (bAllocatedTarget) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + TargetFileName.Buffer); + } + + if(lpTargetFullFileName) + RtlFreeHeap(RtlGetProcessHeap(), 0, lpTargetFullFileName); + + if(pReparseData) + RtlFreeHeap(RtlGetProcessHeap(), 0, pReparseData); + + if(dwErr) + { + SetLastError(dwErr); + return FALSE; + } + + return TRUE; +} + + +/* + * @implemented + */ +BOOLEAN +NTAPI +CreateSymbolicLinkA(IN LPCSTR lpSymlinkFileName, + IN LPCSTR lpTargetFileName, + IN DWORD dwFlags) +{ + PWCHAR SymlinkW, TargetW; + BOOLEAN Ret; + + if(!lpSymlinkFileName || !lpTargetFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!(SymlinkW = FilenameA2W(lpSymlinkFileName, FALSE))) + return FALSE; + + if (!(TargetW = FilenameA2W(lpTargetFileName, TRUE))) + return FALSE; + + Ret = CreateSymbolicLinkW(SymlinkW, + TargetW, + dwFlags); + + RtlFreeHeap(RtlGetProcessHeap(), 0, SymlinkW); + RtlFreeHeap(RtlGetProcessHeap(), 0, TargetW); + + return Ret; +} + +/* + * @unimplemented + */ +DWORD +WINAPI +GetFinalPathNameByHandleW(IN HANDLE hFile, + OUT LPWSTR lpszFilePath, + IN DWORD cchFilePath, + IN DWORD dwFlags) +{ + if (dwFlags & ~(VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NT | + VOLUME_NAME_NONE | FILE_NAME_NORMALIZED | FILE_NAME_OPENED)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + UNIMPLEMENTED; + return 0; +} + +/* + * @implemented + */ +DWORD +WINAPI +GetFinalPathNameByHandleA(IN HANDLE hFile, + OUT LPSTR lpszFilePath, + IN DWORD cchFilePath, + IN DWORD dwFlags) +{ + WCHAR FilePathW[MAX_PATH]; + UNICODE_STRING FilePathU; + DWORD PrevLastError; + DWORD Ret = 0; + + if (cchFilePath != 0 && + cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0])) + { + FilePathU.Length = 0; + FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR); + FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + FilePathU.MaximumLength); + if (FilePathU.Buffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + else + { + FilePathU.Length = 0; + FilePathU.MaximumLength = sizeof(FilePathW); + FilePathU.Buffer = FilePathW; + } + + /* save the last error code */ + PrevLastError = GetLastError(); + SetLastError(ERROR_SUCCESS); + + /* call the unicode version that does all the work */ + Ret = GetFinalPathNameByHandleW(hFile, + FilePathU.Buffer, + cchFilePath, + dwFlags); + + if (GetLastError() == ERROR_SUCCESS) + { + /* no error, restore the last error code and convert the string */ + SetLastError(PrevLastError); + + Ret = FilenameU2A_FitOrFail(lpszFilePath, + cchFilePath, + &FilePathU); + } + + /* free allocated memory if necessary */ + if (FilePathU.Buffer != FilePathW) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + FilePathU.Buffer); + } + + return Ret; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +SetFileBandwidthReservation(IN HANDLE hFile, + IN DWORD nPeriodMilliseconds, + IN DWORD nBytesPerPeriod, + IN BOOL bDiscardable, + OUT LPDWORD lpTransferSize, + OUT LPDWORD lpNumOutstandingRequests) +{ + UNIMPLEMENTED; + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +GetFileBandwidthReservation(IN HANDLE hFile, + OUT LPDWORD lpPeriodMilliseconds, + OUT LPDWORD lpBytesPerPeriod, + OUT LPBOOL pDiscardable, + OUT LPDWORD lpTransferSize, + OUT LPDWORD lpNumOutstandingRequests) +{ + UNIMPLEMENTED; + return FALSE; +} + + +/* + * @unimplemented + */ +BOOL +WINAPI +SetFileCompletionNotificationModes(IN HANDLE FileHandle, + IN UCHAR Flags) +{ + if (Flags & ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + UNIMPLEMENTED; + return FALSE; +} + + +/* + * @unimplemented + */ +HANDLE +WINAPI +OpenFileById(IN HANDLE hFile, + IN LPFILE_ID_DESCRIPTOR lpFileID, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL, + IN DWORD dwFlags) +{ + UNIMPLEMENTED; + return INVALID_HANDLE_VALUE; +} + +#endif + +/* + * @implemented + */ +ULONGLONG +WINAPI +GetTickCount64(VOID) +{ + ULARGE_INTEGER TickCount; + + while (TRUE) + { + TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time; + TickCount.LowPart = SharedUserData->TickCount.LowPart; + + if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) break; + + YieldProcessor(); + } + + return (UInt32x32To64(TickCount.LowPart, SharedUserData->TickCountMultiplier) >> 24) + + (UInt32x32To64(TickCount.HighPart, SharedUserData->TickCountMultiplier) << 8); +} diff --git a/dll/win32/kernel32/debug/debugger.c b/dll/win32/kernel32/debug/debugger.c deleted file mode 100644 index 2604a4c92a2..00000000000 --- a/dll/win32/kernel32/debug/debugger.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/debug/debugger.c - * PURPOSE: Wrappers for the NT Debug Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -typedef struct _DBGSS_THREAD_DATA -{ - struct _DBGSS_THREAD_DATA *Next; - HANDLE ThreadHandle; - HANDLE ProcessHandle; - DWORD ProcessId; - DWORD ThreadId; - BOOLEAN HandleMarked; -} DBGSS_THREAD_DATA, *PDBGSS_THREAD_DATA; - -#define DbgSsSetThreadData(d) \ - NtCurrentTeb()->DbgSsReserved[0] = d - -#define DbgSsGetThreadData() \ - ((PDBGSS_THREAD_DATA)NtCurrentTeb()->DbgSsReserved[0]) - -/* PRIVATE FUNCTIONS *********************************************************/ - -VOID -WINAPI -SaveThreadHandle(IN DWORD dwProcessId, - IN DWORD dwThreadId, - IN HANDLE hThread) -{ - PDBGSS_THREAD_DATA ThreadData; - - /* Allocate a thread structure */ - ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(DBGSS_THREAD_DATA)); - if (!ThreadData) return; - - /* Fill it out */ - ThreadData->ThreadHandle = hThread; - ThreadData->ProcessId = dwProcessId; - ThreadData->ThreadId = dwThreadId; - ThreadData->ProcessHandle = NULL; - ThreadData->HandleMarked = FALSE; - - /* Link it */ - ThreadData->Next = DbgSsGetThreadData(); - DbgSsSetThreadData(ThreadData); -} - -VOID -WINAPI -SaveProcessHandle(IN DWORD dwProcessId, - IN HANDLE hProcess) -{ - PDBGSS_THREAD_DATA ThreadData; - - /* Allocate a thread structure */ - ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(DBGSS_THREAD_DATA)); - if (!ThreadData) return; - - /* Fill it out */ - ThreadData->ProcessHandle = hProcess; - ThreadData->ProcessId = dwProcessId; - ThreadData->ThreadId = 0; - ThreadData->ThreadHandle = NULL; - ThreadData->HandleMarked = FALSE; - - /* Link it */ - ThreadData->Next = DbgSsGetThreadData(); - DbgSsSetThreadData(ThreadData); -} - -VOID -WINAPI -MarkThreadHandle(IN DWORD dwThreadId) -{ - PDBGSS_THREAD_DATA ThreadData; - - /* Loop all thread data events */ - ThreadData = DbgSsGetThreadData(); - while (ThreadData) - { - /* Check if this one matches */ - if (ThreadData->ThreadId == dwThreadId) - { - /* Mark the structure and break out */ - ThreadData->HandleMarked = TRUE; - break; - } - - /* Move to the next one */ - ThreadData = ThreadData->Next; - } -} - -VOID -WINAPI -MarkProcessHandle(IN DWORD dwProcessId) -{ - PDBGSS_THREAD_DATA ThreadData; - - /* Loop all thread data events */ - ThreadData = DbgSsGetThreadData(); - while (ThreadData) - { - /* Check if this one matches */ - if (ThreadData->ProcessId == dwProcessId) - { - /* Make sure the thread ID is empty */ - if (!ThreadData->ThreadId) - { - /* Mark the structure and break out */ - ThreadData->HandleMarked = TRUE; - break; - } - } - - /* Move to the next one */ - ThreadData = ThreadData->Next; - } -} - -VOID -WINAPI -RemoveHandles(IN DWORD dwProcessId, - IN DWORD dwThreadId) -{ - PDBGSS_THREAD_DATA ThreadData; - - /* Loop all thread data events */ - ThreadData = DbgSsGetThreadData(); - while (ThreadData) - { - /* Check if this one matches */ - if (ThreadData->ProcessId == dwProcessId) - { - /* Make sure the thread ID matches too */ - if (ThreadData->ThreadId == dwThreadId) - { - /* Check if we have a thread handle */ - if (ThreadData->ThreadHandle) - { - /* Close it */ - CloseHandle(ThreadData->ThreadHandle); - } - - /* Check if we have a process handle */ - if (ThreadData->ProcessHandle) - { - /* Close it */ - CloseHandle(ThreadData->ProcessHandle); - } - - /* Unlink the thread data */ - DbgSsSetThreadData(ThreadData->Next); - - /* Free it*/ - RtlFreeHeap(RtlGetProcessHeap(), 0, ThreadData); - - /* Move to the next structure */ - ThreadData = DbgSsGetThreadData(); - continue; - } - } - - /* Move to the next one */ - ThreadData = ThreadData->Next; - } -} - -VOID -WINAPI -CloseAllProcessHandles(IN DWORD dwProcessId) -{ - PDBGSS_THREAD_DATA ThreadData; - - /* Loop all thread data events */ - ThreadData = DbgSsGetThreadData(); - while (ThreadData) - { - /* Check if this one matches */ - if (ThreadData->ProcessId == dwProcessId) - { - /* Check if we have a thread handle */ - if (ThreadData->ThreadHandle) - { - /* Close it */ - CloseHandle(ThreadData->ThreadHandle); - } - - /* Check if we have a process handle */ - if (ThreadData->ProcessHandle) - { - /* Close it */ - CloseHandle(ThreadData->ProcessHandle); - } - - /* Unlink the thread data */ - DbgSsSetThreadData(ThreadData->Next); - - /* Free it*/ - RtlFreeHeap(RtlGetProcessHeap(), 0, ThreadData); - - /* Move to the next structure */ - ThreadData = DbgSsGetThreadData(); - continue; - } - - /* Move to the next one */ - ThreadData = ThreadData->Next; - } -} - -HANDLE -WINAPI -ProcessIdToHandle(IN DWORD dwProcessId) -{ - NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE Handle; - CLIENT_ID ClientId; - - /* If we don't have a PID, look it up */ - if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId(); - - /* Open a handle to the process */ - ClientId.UniqueThread = NULL; - ClientId.UniqueProcess = UlongToHandle(dwProcessId); - InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); - Status = NtOpenProcess(&Handle, - PROCESS_ALL_ACCESS, - &ObjectAttributes, - &ClientId); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - SetLastErrorByStatus(Status); - return 0; - } - - /* Return the handle */ - return Handle; -} - -/* PUBLIC FUNCTIONS **********************************************************/ - -/* - * @implemented - */ -BOOL -WINAPI -CheckRemoteDebuggerPresent(IN HANDLE hProcess, - OUT PBOOL pbDebuggerPresent) -{ - HANDLE DebugPort; - NTSTATUS Status; - - /* Make sure we have an output and process*/ - if (!(pbDebuggerPresent) || !(hProcess)) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Check if the process has a debug object/port */ - Status = NtQueryInformationProcess(hProcess, - ProcessDebugPort, - (PVOID)&DebugPort, - sizeof(HANDLE), - NULL); - if (NT_SUCCESS(Status)) - { - /* Return the current state */ - *pbDebuggerPresent = (DebugPort) ? TRUE : FALSE; - return TRUE; - } - - /* Otherwise, fail */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* - * @implemented - */ -BOOL -WINAPI -ContinueDebugEvent(IN DWORD dwProcessId, - IN DWORD dwThreadId, - IN DWORD dwContinueStatus) -{ - CLIENT_ID ClientId; - NTSTATUS Status; - - /* Set the Client ID */ - ClientId.UniqueProcess = (HANDLE)dwProcessId; - ClientId.UniqueThread = (HANDLE)dwThreadId; - - /* Continue debugging */ - Status = DbgUiContinue(&ClientId, dwContinueStatus); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Remove the process/thread handles */ - RemoveHandles(dwProcessId, dwThreadId); - - /* Success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -DebugActiveProcess(IN DWORD dwProcessId) -{ - NTSTATUS Status; - HANDLE Handle; - - /* Connect to the debugger */ - Status = DbgUiConnectToDbg(); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Get the process handle */ - Handle = ProcessIdToHandle(dwProcessId); - if (!Handle) return FALSE; - - /* Now debug the process */ - Status = DbgUiDebugActiveProcess(Handle); - NtClose(Handle); - - /* Check if debugging worked */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -DebugActiveProcessStop(IN DWORD dwProcessId) -{ - NTSTATUS Status; - HANDLE Handle; - - /* Get the process handle */ - Handle = ProcessIdToHandle(dwProcessId); - if (!Handle) return FALSE; - - /* Close all the process handles */ - CloseAllProcessHandles(dwProcessId); - - /* Now stop debgging the process */ - Status = DbgUiStopDebugging(Handle); - NtClose(Handle); - - /* Check for failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } - - /* Success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -DebugBreakProcess(IN HANDLE Process) -{ - NTSTATUS Status; - - /* Send the breakin request */ - Status = DbgUiIssueRemoteBreakin(Process); - if(!NT_SUCCESS(Status)) - { - /* Failure */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -DebugSetProcessKillOnExit(IN BOOL KillOnExit) -{ - HANDLE Handle; - NTSTATUS Status; - ULONG State; - - /* Get the debug object */ - Handle = DbgUiGetThreadDebugObject(); - if (!Handle) - { - /* Fail */ - SetLastErrorByStatus(STATUS_INVALID_HANDLE); - return FALSE; - } - - /* Now set the kill-on-exit state */ - State = KillOnExit; - Status = NtSetInformationDebugObject(Handle, - DebugObjectKillProcessOnExitInformation, - &State, - sizeof(State), - NULL); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -IsDebuggerPresent(VOID) -{ - return (BOOL)NtCurrentPeb()->BeingDebugged; -} - -/* - * @implemented - */ -BOOL -WINAPI -WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, - IN DWORD dwMilliseconds) -{ - LARGE_INTEGER WaitTime; - PLARGE_INTEGER Timeout; - DBGUI_WAIT_STATE_CHANGE WaitStateChange; - NTSTATUS Status; - - /* Check if this is an infinite wait */ - if (dwMilliseconds == INFINITE) - { - /* Under NT, this means no timer argument */ - Timeout = NULL; - } - else - { - /* Otherwise, convert the time to NT Format */ - WaitTime.QuadPart = UInt32x32To64(-10000, dwMilliseconds); - Timeout = &WaitTime; - } - - /* Loop while we keep getting interrupted */ - do - { - /* Call the native API */ - Status = DbgUiWaitStateChange(&WaitStateChange, Timeout); - } while ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC)); - - /* Check if the wait failed */ - if (!(NT_SUCCESS(Status)) || (Status == DBG_UNABLE_TO_PROVIDE_HANDLE)) - { - /* Set the error code and quit */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Check if we timed out */ - if (Status == STATUS_TIMEOUT) - { - /* Fail with a timeout error */ - SetLastError(ERROR_SEM_TIMEOUT); - return FALSE; - } - - /* Convert the structure */ - Status = DbgUiConvertStateChangeStructure(&WaitStateChange, lpDebugEvent); - if (!NT_SUCCESS(Status)) - { - /* Set the error code and quit */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Check what kind of event this was */ - switch (lpDebugEvent->dwDebugEventCode) - { - /* New thread was created */ - case CREATE_THREAD_DEBUG_EVENT: - - /* Setup the thread data */ - SaveThreadHandle(lpDebugEvent->dwProcessId, - lpDebugEvent->dwThreadId, - lpDebugEvent->u.CreateThread.hThread); - break; - - /* New process was created */ - case CREATE_PROCESS_DEBUG_EVENT: - - /* Setup the process data */ - SaveProcessHandle(lpDebugEvent->dwProcessId, - lpDebugEvent->u.CreateProcessInfo.hProcess); - - /* Setup the thread data */ - SaveThreadHandle(lpDebugEvent->dwProcessId, - lpDebugEvent->dwThreadId, - lpDebugEvent->u.CreateThread.hThread); - break; - - /* Process was exited */ - case EXIT_PROCESS_DEBUG_EVENT: - - /* Mark the thread data as such */ - MarkProcessHandle(lpDebugEvent->dwProcessId); - break; - - /* Thread was exited */ - case EXIT_THREAD_DEBUG_EVENT: - - /* Mark the thread data */ - MarkThreadHandle(lpDebugEvent->dwThreadId); - break; - - /* Nothing to do for anything else */ - default: - break; - } - - /* Return success */ - return TRUE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/debug/output.c b/dll/win32/kernel32/debug/output.c deleted file mode 100644 index 30abec99a5d..00000000000 --- a/dll/win32/kernel32/debug/output.c +++ /dev/null @@ -1,438 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/debug/debugger.c - * PURPOSE: OutputDebugString() - * PROGRAMMER: KJK::Hyperion - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* FUNCTIONS *****************************************************************/ - -/* Open or create the mutex used to communicate with the debug monitor */ -static -HANDLE -K32CreateDBMonMutex(void) -{ - static SID_IDENTIFIER_AUTHORITY siaNTAuth = {SECURITY_NT_AUTHORITY}; - static SID_IDENTIFIER_AUTHORITY siaWorldAuth = {SECURITY_WORLD_SID_AUTHORITY}; - HANDLE hMutex; - - /* SIDs to be used in the DACL */ - PSID psidSystem = NULL; - PSID psidAdministrators = NULL; - PSID psidEveryone = NULL; - - /* buffer for the DACL */ - PVOID pDaclBuf = NULL; - - /* minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE - headers. We'll add the size of SIDs when we'll know it - */ - SIZE_T nDaclBufSize = - sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - - sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart)) * 3; - - /* security descriptor of the mutex */ - SECURITY_DESCRIPTOR sdMutexSecurity; - - /* attributes of the mutex object we'll create */ - SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs), - &sdMutexSecurity, - TRUE}; - - NTSTATUS nErrCode; - - /* first, try to open the mutex */ - hMutex = OpenMutexW (SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, - TRUE, - L"DBWinMutex"); - - if(hMutex != NULL) - { - /* success */ - return hMutex; - } - /* error other than the mutex not being found */ - else if(GetLastError() != ERROR_FILE_NOT_FOUND) - { - /* failure */ - return NULL; - } - - /* if the mutex doesn't exist, create it */ - - /* first, set up the mutex security */ - /* allocate the NT AUTHORITY\SYSTEM SID */ - nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, - 1, - SECURITY_LOCAL_SYSTEM_RID, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - &psidSystem); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* allocate the BUILTIN\Administrators SID */ - nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, - 0, - 0, - 0, - 0, - 0, - &psidAdministrators); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* allocate the Everyone SID */ - nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - &psidEveryone); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* allocate space for the SIDs too */ - nDaclBufSize += RtlLengthSid(psidSystem); - nDaclBufSize += RtlLengthSid(psidAdministrators); - nDaclBufSize += RtlLengthSid(psidEveryone); - - /* allocate the buffer for the DACL */ - pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize); - - /* failure */ - if(pDaclBuf == NULL) goto l_Cleanup; - - /* create the DACL */ - nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* grant the minimum required access to Everyone */ - nErrCode = RtlAddAccessAllowedAce(pDaclBuf, - ACL_REVISION, - SYNCHRONIZE | - READ_CONTROL | - MUTANT_QUERY_STATE, - psidEveryone); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* grant full access to BUILTIN\Administrators */ - nErrCode = RtlAddAccessAllowedAce(pDaclBuf, - ACL_REVISION, - MUTANT_ALL_ACCESS, - psidAdministrators); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* grant full access to NT AUTHORITY\SYSTEM */ - nErrCode = RtlAddAccessAllowedAce(pDaclBuf, - ACL_REVISION, - MUTANT_ALL_ACCESS, - psidSystem); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* create the security descriptor */ - nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity, - SECURITY_DESCRIPTOR_REVISION); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* set the descriptor's DACL to the ACL we created */ - nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity, - TRUE, - pDaclBuf, - FALSE); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; - - /* create the mutex */ - hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex"); - -l_Cleanup: - /* free the buffers */ - if(pDaclBuf) GlobalFree(pDaclBuf); - if(psidEveryone) RtlFreeSid(psidEveryone); - if(psidAdministrators) RtlFreeSid(psidAdministrators); - if(psidSystem) RtlFreeSid(psidSystem); - - return hMutex; -} - - -/* - * @implemented - */ -VOID -WINAPI -OutputDebugStringA(LPCSTR _OutputString) -{ - _SEH2_TRY - { - ULONG_PTR a_nArgs[2]; - - a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1); - a_nArgs[1] = (ULONG_PTR)_OutputString; - - /* send the string to the user-mode debugger */ - RaiseException(DBG_PRINTEXCEPTION_C, 0, 2, a_nArgs); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* no user-mode debugger: try the systemwide debug message monitor, or the - kernel debugger as a last resort */ - - /* mutex used to synchronize invocations of OutputDebugString */ - static HANDLE s_hDBMonMutex = NULL; - /* true if we already attempted to open/create the mutex */ - static BOOL s_bDBMonMutexTriedOpen = FALSE; - - /* local copy of the mutex handle */ - volatile HANDLE hDBMonMutex = s_hDBMonMutex; - /* handle to the Section of the shared buffer */ - volatile HANDLE hDBMonBuffer = NULL; - - /* pointer to the mapped view of the shared buffer. It consist of the current - process id followed by the message string */ - struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL; - - /* event: signaled by the debug message monitor when OutputDebugString can write - to the shared buffer */ - volatile HANDLE hDBMonBufferReady = NULL; - - /* event: to be signaled by OutputDebugString when it's done writing to the - shared buffer */ - volatile HANDLE hDBMonDataReady = NULL; - - /* mutex not opened, and no previous attempts to open/create it */ - if(hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen) - { - /* open/create the mutex */ - hDBMonMutex = K32CreateDBMonMutex(); - /* store the handle */ - s_hDBMonMutex = hDBMonMutex; - } - - _SEH2_TRY - { - volatile PCHAR a_cBuffer = NULL; - - /* opening the mutex failed */ - if(hDBMonMutex == NULL) - { - /* remember next time */ - s_bDBMonMutexTriedOpen = TRUE; - } - /* opening the mutex succeeded */ - else - { - do - { - /* synchronize with other invocations of OutputDebugString */ - WaitForSingleObject(hDBMonMutex, INFINITE); - - /* buffer of the system-wide debug message monitor */ - hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE, L"DBWIN_BUFFER"); - - /* couldn't open the buffer: send the string to the kernel debugger */ - if(hDBMonBuffer == NULL) break; - - /* map the buffer */ - pDBMonBuffer = MapViewOfFile(hDBMonBuffer, - SECTION_MAP_READ | SECTION_MAP_WRITE, - 0, - 0, - 0); - - /* couldn't map the buffer: send the string to the kernel debugger */ - if(pDBMonBuffer == NULL) break; - - /* open the event signaling that the buffer can be accessed */ - hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY"); - - /* couldn't open the event: send the string to the kernel debugger */ - if(hDBMonBufferReady == NULL) break; - - /* open the event to be signaled when the buffer has been filled */ - hDBMonDataReady = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"DBWIN_DATA_READY"); - } - while(0); - - /* we couldn't connect to the system-wide debug message monitor: send the - string to the kernel debugger */ - if(hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex); - } - - _SEH2_TRY - { - /* size of the current output block */ - volatile SIZE_T nRoundLen; - - /* size of the remainder of the string */ - volatile SIZE_T nOutputStringLen; - - /* output the whole string */ - nOutputStringLen = strlen(_OutputString); - - do - { - /* we're connected to the debug monitor: - write the current block to the shared buffer */ - if(hDBMonDataReady) - { - /* wait a maximum of 10 seconds for the debug monitor - to finish processing the shared buffer */ - if(WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0) - { - /* timeout or failure: give up */ - break; - } - - /* write the process id into the buffer */ - pDBMonBuffer->ProcessId = GetCurrentProcessId(); - - /* write only as many bytes as they fit in the buffer */ - if(nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1)) - nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1; - else - nRoundLen = nOutputStringLen; - - /* copy the current block into the buffer */ - memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen); - - /* null-terminate the current block */ - pDBMonBuffer->Buffer[nRoundLen] = 0; - - /* signal that the data contains meaningful data and can be read */ - SetEvent(hDBMonDataReady); - } - /* else, send the current block to the kernel debugger */ - else - { - /* output in blocks of 512 characters */ - a_cBuffer = (CHAR*)HeapAlloc(GetProcessHeap(), 0, 512); - - if (!a_cBuffer) - { - DbgPrint("OutputDebugStringA: Failed\n"); - break; - } - - /* write a maximum of 511 bytes */ - if(nOutputStringLen > 510) - nRoundLen = 510; - else - nRoundLen = nOutputStringLen; - - /* copy the current block */ - memcpy(a_cBuffer, _OutputString, nRoundLen); - - /* null-terminate the current block */ - a_cBuffer[nRoundLen] = 0; - - /* send the current block to the kernel debugger */ - DbgPrint("%s", a_cBuffer); - - if (a_cBuffer) - { - HeapFree(GetProcessHeap(), 0, a_cBuffer); - a_cBuffer = NULL; - } - } - - /* move to the next block */ - _OutputString += nRoundLen; - nOutputStringLen -= nRoundLen; - } - /* repeat until the string has been fully output */ - while (nOutputStringLen > 0); - } - /* ignore access violations and let other exceptions fall through */ - _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) - { - if (a_cBuffer) - HeapFree(GetProcessHeap(), 0, a_cBuffer); - - /* string copied verbatim from Microsoft's kernel32.dll */ - DbgPrint("\nOutputDebugString faulted during output\n"); - } - _SEH2_END; - } - _SEH2_FINALLY - { - /* close all the still open resources */ - if(hDBMonBufferReady) CloseHandle(hDBMonBufferReady); - if(pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer); - if(hDBMonBuffer) CloseHandle(hDBMonBuffer); - if(hDBMonDataReady) CloseHandle(hDBMonDataReady); - - /* leave the critical section */ - if(hDBMonDataReady != NULL) - ReleaseMutex(hDBMonMutex); - } - _SEH2_END; - } - _SEH2_END; -} - - -/* - * @implemented - */ -VOID -WINAPI -OutputDebugStringW(LPCWSTR _OutputString) -{ - UNICODE_STRING wstrOut; - ANSI_STRING strOut; - NTSTATUS nErrCode; - - /* convert the string in ANSI */ - RtlInitUnicodeString(&wstrOut, _OutputString); - nErrCode = RtlUnicodeStringToAnsiString(&strOut, &wstrOut, TRUE); - - if(!NT_SUCCESS(nErrCode)) - { - /* Microsoft's kernel32.dll always prints something, even in case the conversion fails */ - OutputDebugStringA(""); - } - else - { - /* output the converted string */ - OutputDebugStringA(strOut.Buffer); - - /* free the converted string */ - RtlFreeAnsiString(&strOut); - } -} diff --git a/dll/win32/kernel32/file/find.c b/dll/win32/kernel32/file/find.c index 0060e662889..3cd0ef9cbe0 100644 --- a/dll/win32/kernel32/file/find.c +++ b/dll/win32/kernel32/file/find.c @@ -259,7 +259,7 @@ InternalFindFirstFile ( PWSTR NtPathBuffer; BOOLEAN RemovedLastChar = FALSE; BOOL bResult; - CURDIR DirInfo; + RTL_RELATIVE_NAME_U DirInfo; ULONG DeviceNameInfo; HANDLE hDirectory = NULL; @@ -292,20 +292,20 @@ InternalFindFirstFile ( } PathFileName.MaximumLength = PathFileName.Length; - if (DirInfo.DosPath.Length != 0 && DirInfo.DosPath.Buffer != PathFileName.Buffer) + if (DirInfo.RelativeName.Length != 0 && DirInfo.RelativeName.Buffer != PathFileName.Buffer) { if (PathFileName.Buffer != NULL) { - /* This is a relative path to DirInfo.Handle, adjust NtPathU! */ + /* This is a relative path to DirInfo.ContainingDirectory, adjust NtPathU! */ NtPathU.Length = NtPathU.MaximumLength = - (USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)DirInfo.DosPath.Buffer); - NtPathU.Buffer = DirInfo.DosPath.Buffer; + (USHORT)((ULONG_PTR)PathFileName.Buffer - (ULONG_PTR)DirInfo.RelativeName.Buffer); + NtPathU.Buffer = DirInfo.RelativeName.Buffer; } } else { /* This is an absolute path, NtPathU receives the full path */ - DirInfo.Handle = NULL; + DirInfo.ContainingDirectory = NULL; if (PathFileName.Buffer != NULL) { NtPathU.Length = NtPathU.MaximumLength = @@ -332,12 +332,12 @@ InternalFindFirstFile ( TRACE("lpFileName: \"%ws\"\n", lpFileName); TRACE("NtPathU: \"%wZ\"\n", &NtPathU); TRACE("PathFileName: \"%wZ\"\n", &PathFileName); - TRACE("RelativeTo: 0x%p\n", DirInfo.Handle); + TRACE("RelativeTo: 0x%p\n", DirInfo.ContainingDirectory); InitializeObjectAttributes (&ObjectAttributes, &NtPathU, OBJ_CASE_INSENSITIVE, - DirInfo.Handle, + DirInfo.ContainingDirectory, NULL); Status = NtOpenFile (&hDirectory, diff --git a/dll/win32/kernel32/include/base_x.h b/dll/win32/kernel32/include/base_x.h new file mode 100644 index 00000000000..a7457190cfc --- /dev/null +++ b/dll/win32/kernel32/include/base_x.h @@ -0,0 +1,158 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS System Libraries + * FILE: dll/win32/kernel32/include/base_x.h + * PURPOSE: Base API Client Macros + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + */ + +#pragma once + +/* INCLUDES *******************************************************************/ + +// +// This macro (split it up in 3 pieces to allow for intermediary code in between) +// converts a NULL-terminated ASCII string, usually associated with an object +// name, into its NT-native UNICODE_STRING structure, by using the TEB's Static +// Unicode String. +// +// It should only be used when the name is supposed to be less than MAX_PATH +// (260 characters). +// +// It returns the correct ERROR_FILENAME_EXCED_RANGE Win32 error when the path +// is too long. +// +// Note that Basep8BitStringToStaticUnicodeString looks deceptively similar. +// However, that function was designed for File APIs, which can be switched into +// a special "OEM" mode, that uses different NLS files/encoding, and thus calls +// RtlOemStringToAnsiString (see SetFileApisToOEM). Thererefore, this macro and +// that function are not interchangeable. As a separate note, that function uses +// the *Ex version of the Rtl conversion APIs, which does stricter checking that +// is not done when this macro is used. +// +#define ConvertAnsiToUnicodePrologue \ +{ \ + NTSTATUS Status; \ + PUNICODE_STRING UnicodeCache; \ + ANSI_STRING AnsiName; +#define ConvertAnsiToUnicodeBody(name) \ + UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; \ + RtlInitAnsiString(&AnsiName, name); \ + Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); +#define ConvertAnsiToUnicodeEpilogue \ + if (Status == STATUS_BUFFER_OVERFLOW) \ + SetLastError(ERROR_FILENAME_EXCED_RANGE); \ + else \ + BaseSetLastNTError(Status); \ + return FALSE; \ +} + +// +// This macro uses the ConvertAnsiToUnicode macros above to convert a CreateXxxA +// Win32 API into its equivalent CreateXxxW API. +// +#define ConvertWin32AnsiObjectApiToUnicodeApi(obj, name, ...) \ + ConvertAnsiToUnicodePrologue \ + if (!name) return Create##obj##W(__VA_ARGS__, NULL); \ + ConvertAnsiToUnicodeBody(name) \ + if (NT_SUCCESS(Status)) return Create##obj##W(__VA_ARGS__, UnicodeCache->Buffer); \ + ConvertAnsiToUnicodeEpilogue + +// +// This macro uses the ConvertAnsiToUnicode macros above to convert a FindFirst*A +// Win32 API into its equivalent FindFirst*W API. +// +#define ConvertWin32AnsiChangeApiToUnicodeApi(obj, name, ...) \ + ConvertAnsiToUnicodePrologue \ + ConvertAnsiToUnicodeBody(name) \ + if (NT_SUCCESS(Status)) return obj##W(UnicodeCache->Buffer, ##__VA_ARGS__); \ + ConvertAnsiToUnicodeEpilogue + +// +// This macro uses the ConvertAnsiToUnicode macros above to convert a OpenXxxA +// Win32 API into its equivalent OpenXxxW API. +// +#define ConvertOpenWin32AnsiObjectApiToUnicodeApi(obj, acc, inh, name) \ + ConvertAnsiToUnicodePrologue \ + if (!name) \ + { \ + SetLastError(ERROR_INVALID_PARAMETER); \ + return NULL; \ + } \ + ConvertAnsiToUnicodeBody(name) \ + if (NT_SUCCESS(Status)) return Open##obj##W(acc, inh, UnicodeCache->Buffer);\ + ConvertAnsiToUnicodeEpilogue + +// +// This macro (split it up in 3 pieces to allow for intermediary code in between) +// wraps the usual code path required to create an NT object based on a Unicode +// (Wide) Win32 object creation API. +// +// It makes use of BasepConvertObjectAttributes and allows for a custom access +// mode to be used, and also sets the correct error codes in case of a collision +// +#define CreateNtObjectFromWin32ApiPrologue \ +{ \ + NTSTATUS Status; \ + HANDLE Handle; \ + UNICODE_STRING ObjectName; \ + OBJECT_ATTRIBUTES LocalAttributes; \ + POBJECT_ATTRIBUTES ObjectAttributes = &LocalAttributes; +#define CreateNtObjectFromWin32ApiBody(ntobj, sec, name, access, ...) \ + if (name) RtlInitUnicodeString(&ObjectName, name); \ + ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, \ + sec, \ + name ? &ObjectName : NULL); \ + Status = NtCreate##ntobj(&Handle, access, ObjectAttributes, ##__VA_ARGS__); +#define CreateNtObjectFromWin32ApiEpilogue \ + if (NT_SUCCESS(Status)) \ + { \ + if (Status == STATUS_OBJECT_NAME_EXISTS) \ + SetLastError(ERROR_ALREADY_EXISTS); \ + else \ + SetLastError(ERROR_SUCCESS); \ + return Handle; \ + } \ + BaseSetLastNTError(Status); \ + return NULL; \ +} + +// +// This macro uses the CreateNtObjectFromWin32Api macros from above to create an +// NT object based on the Win32 API settings. +// +// Note that it is hardcoded to always use XXX_ALL_ACCESS permissions, which is +// the behavior up until Vista. When/if the target moves to Vista, the macro can +// be improved to support caller-specified access masks, as the underlying macro +// above does support this. +// +#define CreateNtObjectFromWin32Api(obj, ntobj, capsobj, sec, name, ...) \ + CreateNtObjectFromWin32ApiPrologue \ + CreateNtObjectFromWin32ApiBody(ntobj, sec, name, capsobj##_ALL_ACCESS, ##__VA_ARGS__); \ + CreateNtObjectFromWin32ApiEpilogue + +// +// This macro opens an NT object based on the Win32 API settings. +// +#define OpenNtObjectFromWin32Api(ntobj, acc, inh, name) \ + CreateNtObjectFromWin32ApiPrologue \ + if (!name) \ + { \ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); \ + return NULL; \ + } \ + RtlInitUnicodeString(&ObjectName, name); \ + InitializeObjectAttributes(ObjectAttributes, \ + &ObjectName, \ + inh ? OBJ_INHERIT : 0, \ + hBaseDir, \ + NULL); \ + Status = NtOpen##ntobj(&Handle, acc, ObjectAttributes); \ + if (!NT_SUCCESS(Status)) \ + { \ + BaseSetLastNTError(Status); \ + return NULL; \ + } \ + return Handle; \ +} + diff --git a/dll/win32/kernel32/include/kernel32.h b/dll/win32/kernel32/include/kernel32.h index b315c2ed69f..ec4109f3551 100644 --- a/dll/win32/kernel32/include/kernel32.h +++ b/dll/win32/kernel32/include/kernel32.h @@ -21,6 +21,10 @@ #define FIXME(fmt, ...) WARN__(gDebugChannel, fmt,## __VA_ARGS__) #define ERR(fmt, ...) ERR__(gDebugChannel, fmt, ##__VA_ARGS__) +#define STUB \ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); \ + DPRINT1("%s() is UNIMPLEMENTED!\n", __FUNCTION__) + #define debugstr_a #define debugstr_w #define wine_dbgstr_w @@ -67,8 +71,6 @@ /* Undocumented CreateProcess flag */ #define STARTF_SHELLPRIVATE 0x400 -#define SetLastErrorByStatus(x) RtlSetLastWin32ErrorAndNtStatusFromNtStatus((x)) - typedef struct _CODEPAGE_ENTRY { LIST_ENTRY Entry; @@ -78,6 +80,8 @@ typedef struct _CODEPAGE_ENTRY CPTABLEINFO CodePageTable; } CODEPAGE_ENTRY, *PCODEPAGE_ENTRY; +extern PBASE_STATIC_SERVER_DATA BaseStaticServerData; + typedef DWORD (*WaitForInputIdleType)( @@ -100,6 +104,10 @@ extern PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry; extern LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter; +extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo; + +extern BOOLEAN BaseRunningInServerProcess; + /* FUNCTION PROTOTYPES *******************************************************/ BOOL WINAPI VerifyConsoleIoHandle(HANDLE Handle); @@ -131,6 +139,11 @@ DWORD FilenameU2A_FitOrFail(LPSTR DestA, INT destLen, PUNICODE_STRING SourceU); #define HeapFree RtlFreeHeap #define _lread (_readfun)_hread +PLARGE_INTEGER +WINAPI +BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout, + IN DWORD dwMilliseconds); + POBJECT_ATTRIBUTES WINAPI BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, diff --git a/dll/win32/kernel32/k32.h b/dll/win32/kernel32/k32.h index f59172c8566..553347ce27f 100644 --- a/dll/win32/kernel32/k32.h +++ b/dll/win32/kernel32/k32.h @@ -42,4 +42,7 @@ /* PSEH for SEH Support */ #include +/* Base Macros */ +#include "include/base_x.h" + #endif diff --git a/dll/win32/kernel32/kernel32.rc b/dll/win32/kernel32/kernel32.rc index 319acb78e8f..b8aae5cd9f2 100644 --- a/dll/win32/kernel32/kernel32.rc +++ b/dll/win32/kernel32/kernel32.rc @@ -7,13 +7,13 @@ #include "windows.h" #include "errcodes.rc" -#include "locale_rc.rc" +#include "winnls/locale_rc.rc" -#include "lang/en-US.rc" -#include "lang/de-DE.rc" -#include "lang/es-ES.rc" +#include "winnls/lang/en-US.rc" +#include "winnls/lang/de-DE.rc" +#include "winnls/lang/es-ES.rc" // UTF-8 #pragma code_page(65001) -#include "lang/ru-RU.rc" -#include "lang/uk-UA.rc" +#include "winnls/lang/ru-RU.rc" +#include "winnls/lang/uk-UA.rc" diff --git a/dll/win32/kernel32/kernel32.spec b/dll/win32/kernel32/kernel32.spec index c0a8bf54022..f43460966e7 100644 --- a/dll/win32/kernel32/kernel32.spec +++ b/dll/win32/kernel32/kernel32.spec @@ -1,62 +1,35 @@ -@ stdcall AcquireSRWLockExclusive(ptr) ntdll.RtlAcquireSRWLockExclusive -@ stdcall AcquireSRWLockShared(ptr) ntdll.RtlAcquireSRWLockShared +#undef i386 @ stdcall ActivateActCtx(ptr ptr) @ stdcall AddAtomA(str) @ stdcall AddAtomW(wstr) @ stdcall AddConsoleAliasA(str str str) ;check @ stdcall AddConsoleAliasW(wstr wstr wstr) ;check -;@ stdcall -arch=x86_64 AddIntegrityLabelToBoundaryDescriptor ; Win 7 @ stdcall AddLocalAlternateComputerNameA(str ptr) @ stdcall AddLocalAlternateComputerNameW(wstr ptr) @ stdcall AddRefActCtx(ptr) -;@ stdcall AddSIDToBoundaryDescriptor ; Win 7 -;@ stdcall AddSecureMemoryCacheCallback ; Win 7 @ stdcall AddVectoredContinueHandler(long ptr) ntdll.RtlAddVectoredContinueHandler @ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler -;@ stdcall AdjustCalendarDate ; Win 7 @ stdcall AllocConsole() -;@ stub AllocLSCallback ; missing in XP SP3 and 2003 R2 and Win 7 @ stdcall AllocateUserPhysicalPages(long ptr ptr) -;@ stdcall AllocateUserPhysicalPagesNuma ; Win 7 -;@ stdcall ApplicationRecoveryFinished ; Win 7 -;@ stdcall ApplicationRecoveryInProgress ; Win 7 @ stdcall AreFileApisANSI() @ stdcall AssignProcessToJobObject(ptr ptr) @ stdcall AttachConsole(long) @ stdcall BackupRead(ptr ptr long ptr long long ptr) @ stdcall BackupSeek(ptr long long ptr ptr ptr) @ stdcall BackupWrite(ptr ptr long ptr long long ptr) -@ stdcall BaseCheckAppcompatCache(long long long ptr) ;check -;@ stdcall BaseCheckAppcompatCacheEx ; Win7 -;@ stub BaseCheckRunApp ; Win7 -@ stdcall BaseCleanupAppcompatCache() ; missing in Win 7 +@ stdcall BaseCheckAppcompatCache(long long long ptr) +@ stdcall BaseCheckRunApp(long ptr long long long long long long long long) @ stdcall BaseCleanupAppcompatCacheSupport(ptr) -;@ stdcall BaseDllReadWriteIniFile ; Win 7 @ stdcall BaseDumpAppcompatCache() @ stdcall BaseFlushAppcompatCache() -;@ stdcall BaseFormatObjectAttributes ; Win 7 -;@ stdcall BaseFormatTimeOut ; Win 7 -;@ stdcall BaseGenerateAppCompatData ; Win 7 -;@ stdcall BaseGetNamedObjectDirectory ; Win 7 -@ stdcall BaseInitAppcompatCache() ; missing in Win 7 @ stdcall BaseInitAppcompatCacheSupport() -;@ stdcall BaseIsAppcompatInfrastructureDisabled ; Win 7 +@ stdcall BaseIsAppcompatInfrastructureDisabled() @ stdcall BaseProcessInitPostImport() ; missing in Win 7 @ stdcall BaseQueryModuleData(str str ptr ptr ptr) ;check -;@ stdcall BaseThreadInitThunk ; Win 7 -;@ stdcall BaseSetLastNTError ; Win 7, not 64 bit (present on w2k3 but not exported) @ stdcall BaseUpdateAppcompatCache(long long long) -;@ stdcall BaseVerifyUnicodeString ; Win 7 -;@ stdcall Basep8BitStringToDynamicUnicodeString ; Win 7 -;@ stdcall BasepAllocateActivationContextActivationBlock ; Win 7 -;@ stdcall BasepAnsiStringToDynamicUnicodeString ; Win 7 -;@ stdcall BasepCheckAppCompat ; Win 7 -;@ stdcall BasepCheckBadapp ; Win 7 +@ stdcall BasepCheckBadapp(long ptr long long long long long long long) @ stdcall BasepCheckWinSaferRestrictions(long long long long long long) -;@ stub BasepDebugDump ; missing in XP SP3 and Win 7 -;@ stdcall BasepFreeActivationContextActivationBlock ; Win 7 -;@ stdcall BasepFreeAppCompatData ; Win 7 -;@ stdcall BasepMapModuleHandle ; Win 7 +@ stdcall BasepFreeAppCompatData(ptr ptr) @ stdcall Beep(long long) @ stdcall BeginUpdateResourceA(str long) @ stdcall BeginUpdateResourceW(wstr long) @@ -67,18 +40,11 @@ @ stdcall BuildCommDCBW(wstr ptr) @ stdcall CallNamedPipeA(str ptr long ptr long ptr long) @ stdcall CallNamedPipeW(wstr ptr long ptr long ptr long) -;@ stdcall CallbackMayRunLong ; Win 7 @ stdcall CancelDeviceWakeupRequest(long) @ stdcall CancelIo(long) -@ stdcall CancelIoEx(long ptr) -@ stdcall CancelSynchronousIo(long) -;@ stdcall CancelThreadpoolIo(ptr) ntdll.TpCancelAsyncIoOperation; Win 7 @ stdcall CancelTimerQueueTimer(long long) @ stdcall CancelWaitableTimer(long) @ stdcall ChangeTimerQueueTimer(ptr ptr long long) -;@ stdcall CheckElevation ; Win 7 -;@ stdcall CheckElevationEnabled ; Win 7 -;@ stdcall CheckForReadOnlyResource ; Win 7 @ stdcall CheckNameLegalDOS8Dot3A(str str long long long) @ stdcall CheckNameLegalDOS8Dot3W(wstr str long long long) @ stdcall CheckRemoteDebuggerPresent(long ptr) @@ -86,125 +52,69 @@ @ stdcall ClearCommError(long ptr ptr) @ stdcall CloseConsoleHandle(long) @ stdcall CloseHandle(long) -;@ stdcall ClosePrivateNamespace ; Win 7 @ stdcall CloseProfileUserMapping() -; @ stub CloseSystemHandle ; missing in XP SP3 and Win 7 -;@ stdcall CloseThreadpool(ptr) ntdll.TpReleasePool ; Win 7 -;@ stdcall CloseThreadpoolCleanupGroup(ptr) ntdll.TpReleaseCleanupGroup ; Win 7 -;@ stdcall CloseThreadpoolCleanupGroupMembers(ptr long ptr) ntdll.TpReleaseCleanupGroupMembers ; Win 7 -;@ stdcall CloseThreadpoolIo ntdll.TpReleaseIoCompletion ; Win 7 -;@ stdcall CloseThreadpoolTimer ntdll.TpReleaseTimer ; Win 7 -;@ stdcall CloseThreadpoolWait ntdll.TpReleaseWait ; Win 7 -;@ stdcall CloseThreadpoolWork ntdll.TpReleaseWork ; Win 7 @ stdcall CmdBatNotification(long) @ stdcall CommConfigDialogA(str long ptr) @ stdcall CommConfigDialogW(wstr long ptr) -;@ stdcall CompareCalendarDates ; Win 7 @ stdcall CompareFileTime(ptr ptr) @ stdcall CompareStringA(long long str long str long) -;@ stdcall CompareStringEx ; Win 7 -;@ stdcall CompareStringOrdinal ; Win 7 @ stdcall CompareStringW(long long wstr long wstr long) @ stdcall ConnectNamedPipe(long ptr) @ stdcall ConsoleMenuControl(long long long) -; @ stub ConsoleSubst ; missing in XP SP3 and Win 7 @ stdcall ContinueDebugEvent(long long long) -;@ stdcall ConvertCalDateTimeToSystemTime ; Win 7 @ stdcall ConvertDefaultLocale (long) @ stdcall ConvertFiberToThread() -;@ stdcall ConvertNLSDayOfWeekToWin32DayOfWeek ; Win 7 -;@ stdcall ConvertSystemTimeToCalDateTime ; Win 7 @ stdcall ConvertThreadToFiber(ptr) @ stdcall ConvertThreadToFiberEx(ptr long) -;@ stdcall CopyExtendedContext ; Win 7 @ stdcall CopyFileA(str str long) @ stdcall CopyFileExA (str str ptr ptr ptr long) @ stdcall CopyFileExW (wstr wstr ptr ptr ptr long) -;@ stdcall CopyFileTransactedA ; Win 7 -;@ stdcall CopyFileTransactedW ; Win 7 @ stdcall CopyFileW(wstr wstr long) @ stdcall CopyLZFile(long long) LZCopy @ stdcall CreateActCtxA(ptr) @ stdcall CreateActCtxW(ptr) -;@ stdcall CreateBoundaryDescriptorA ; Win 7 -;@ stdcall CreateBoundaryDescriptorW ; Win 7 @ stdcall CreateConsoleScreenBuffer(long long ptr long ptr) @ stdcall CreateDirectoryA(str ptr) @ stdcall CreateDirectoryExA(str str ptr) @ stdcall CreateDirectoryExW(wstr wstr ptr) -;@ stdcall CreateDirectoryTransactedA ; Win 7 -;@ stdcall CreateDirectoryTransactedW ; Win 7 @ stdcall CreateDirectoryW(wstr ptr) @ stdcall CreateEventA(ptr long long str) -@ stdcall CreateEventExA(ptr str long long) -@ stdcall CreateEventExW(ptr wstr long long) @ stdcall CreateEventW(ptr long long wstr) @ stdcall CreateFiber(long ptr ptr) @ stdcall CreateFiberEx(long long long ptr ptr) @ stdcall CreateFileA(str long long ptr long long long) @ stdcall CreateFileMappingA(long ptr long long long str) -;@ stdcall CreateFileMappingNumaA ; Win 7 -;@ stdcall CreateFileMappingNumaW ; Win 7 @ stdcall CreateFileMappingW(long ptr long long long wstr) -;@ stdcall CreateFileTransactedA ; Win 7 -;@ stdcall CreateFileTransactedW ; Win 7 @ stdcall CreateFileW(wstr long long ptr long long long) @ stdcall CreateHardLinkA(str str ptr) -;@ stdcall CreateHardLinkTransactedA ; Win 7 -;@ stdcall CreateHardLinkTransactedW ; Win 7 @ stdcall CreateHardLinkW(wstr wstr ptr) @ stdcall CreateIoCompletionPort(long long long long) @ stdcall CreateJobObjectA(ptr str) @ stdcall CreateJobObjectW(ptr wstr) @ stdcall CreateJobSet(long ptr long) -;@ stub CreateKernelThread ; missing in XP SP3 and Win 7 @ stdcall CreateMailslotA(ptr long long ptr) @ stdcall CreateMailslotW(ptr long long ptr) @ stdcall CreateMemoryResourceNotification(long) @ stdcall CreateMutexA(ptr long str) -@ stdcall CreateMutexExA(ptr str long long) -@ stdcall CreateMutexExW(ptr wstr long long) @ stdcall CreateMutexW(ptr long wstr) @ stdcall CreateNamedPipeA(str long long long long long long ptr) @ stdcall CreateNamedPipeW(wstr long long long long long long ptr) @ stdcall CreateNlsSecurityDescriptor(ptr long long) ; missing in Win 7 @ stdcall CreatePipe(ptr ptr ptr long) -;@ stdcall CreatePrivateNamespaceA ; Win 7 -;@ stdcall CreatePrivateNamespaceW ; Win 7 @ stdcall CreateProcessA(str str ptr ptr long long ptr str ptr ptr) -;@ stdcall CreateProcessAsUserW ; Win 7 @ stdcall CreateProcessInternalA(ptr str str ptr ptr long long ptr str ptr ptr long) @ stdcall CreateProcessInternalW(ptr wstr wstr ptr ptr long long ptr wstr ptr ptr long) -@ stdcall CreateProcessInternalWSecure() ; missing in Win 7 @ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr) @ stdcall CreateRemoteThread(long ptr long ptr long long ptr) -;@ stdcall CreateRemoteThreadEx api-ms-win-core-processthreads-l1-1-0.CreateRemoteThreadEx ; Win 7 @ stdcall CreateSemaphoreA(ptr long long str) -@ stdcall CreateSemaphoreExA(ptr long long str long long) -@ stdcall CreateSemaphoreExW(ptr long long wstr long long) @ stdcall CreateSemaphoreW(ptr long long wstr) @ stdcall CreateSocketHandle() -@ stdcall CreateSymbolicLinkA(str str long) -;@ stdcall CreateSymbolicLinkTransactedA ; Win 7 -;@ stdcall CreateSymbolicLinkTransactedW ; Win 7 -@ stdcall CreateSymbolicLinkW(wstr wstr long) @ stdcall CreateTapePartition(long long long long) @ stdcall CreateThread(ptr long ptr long long ptr) -;@ stdcall CreateThreadpool ; Win 7 -;@ stdcall CreateThreadpoolCleanupGroup ; Win 7 -;@ stdcall CreateThreadpoolIo ; Win 7 -;@ stdcall CreateThreadpoolTimer ; Win 7 -;@ stdcall CreateThreadpoolWait ; Win 7 -;@ stdcall CreateThreadpoolWork ; Win 7 @ stdcall CreateTimerQueue () @ stdcall CreateTimerQueueTimer(ptr long ptr ptr long long long) @ stdcall CreateToolhelp32Snapshot(long long) -;@ stdcall arch=x86_64 CreateUmsCompletionList -;@ stdcall arch=x86_64 CreateUmsThreadContext -@ stdcall CreateVirtualBuffer(long long long) ; missing in Win 7 @ stdcall CreateWaitableTimerA(ptr long str) -@ stdcall CreateWaitableTimerExA(ptr str long long) -@ stdcall CreateWaitableTimerExW(ptr wstr long long) @ stdcall CreateWaitableTimerW(ptr long wstr) @ stdcall DeactivateActCtx(long ptr) @ stdcall DebugActiveProcess(long) @@ -218,26 +128,17 @@ @ stdcall DefineDosDeviceW(long wstr wstr) @ stdcall DelayLoadFailureHook(str str) @ stdcall DeleteAtom(long) -;@ stdcall DeleteBoundaryDescriptor ntdll.RtlDeleteBoundaryDescriptor ; Win 7 @ stdcall DeleteCriticalSection(ptr) ntdll.RtlDeleteCriticalSection @ stdcall DeleteFiber(ptr) @ stdcall DeleteFileA(str) -;@ stdcall DeleteFileTransactedA ; Win 7 -;@ stdcall DeleteFileTransactedW ; Win 7 @ stdcall DeleteFileW(wstr) -;@ stdcall DeleteProcThreadAttributeList api-ms-win-core-processthreads-l1-1-0.DeleteProcThreadAttributeList ; Win 7 @ stdcall DeleteTimerQueue(long) @ stdcall DeleteTimerQueueEx (long long) @ stdcall DeleteTimerQueueTimer(long long long) -;@ stdcall -arch=x86_64 DeleteUmsCompletionList -;@ stdcall -arch=x86_64 DeleteUmsThreadContext @ stdcall DeleteVolumeMountPointA(str) ;check @ stdcall DeleteVolumeMountPointW(wstr) ;check -;@ stdcall -arch=x86_64 DequeueUmsCompletionListItems @ stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) @ stdcall DisableThreadLibraryCalls(long) -;@ stdcall DisableThreadProfiling ; Win 7 -;@ stdcall DisassociateCurrentThreadFromCallback ntdll.TpDisassociateCallback ; Win 7 @ stdcall DisconnectNamedPipe(long) @ stdcall DnsHostnameToComputerNameA (str ptr ptr) @ stdcall DnsHostnameToComputerNameW (wstr ptr ptr) @@ -246,48 +147,36 @@ @ stdcall DosPathToSessionPathW(long wstr wstr) @ stdcall DuplicateConsoleHandle(long long long long) @ stdcall DuplicateHandle(long long long ptr long long long) -;@ stdcall EnableThreadProfiling ; Win 7 @ stdcall EncodePointer(ptr) ntdll.RtlEncodePointer @ stdcall EncodeSystemPointer(ptr) ntdll.RtlEncodeSystemPointer @ stdcall EndUpdateResourceA(long long) @ stdcall EndUpdateResourceW(long long) @ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection -;@ stdcall -arch=x86_64 EnterUmsSchedulingMode @ stdcall EnumCalendarInfoA(ptr long long long) @ stdcall EnumCalendarInfoExA(ptr long long long) -;@ stdcall EnumCalendarInfoExEx ; Win 7 @ stdcall EnumCalendarInfoExW(ptr long long long) @ stdcall EnumCalendarInfoW(ptr long long long) @ stdcall EnumDateFormatsA(ptr long long) @ stdcall EnumDateFormatsExA(ptr long long) -;@ stdcall EnumDateFormatsExEx ; Win 7 @ stdcall EnumDateFormatsExW(ptr long long) @ stdcall EnumDateFormatsW(ptr long long) @ stdcall EnumLanguageGroupLocalesA(ptr long long ptr) @ stdcall EnumLanguageGroupLocalesW(ptr long long ptr) @ stdcall EnumResourceLanguagesA(long str str ptr long) -;@ stdcall EnumResourceLanguagesExA ; Win 7 -;@ stdcall EnumResourceLanguagesExW ; Win 7 @ stdcall EnumResourceLanguagesW(long wstr wstr ptr long) @ stdcall EnumResourceNamesA(long str ptr long) -;@ stdcall EnumResourceNamesExA ; Win 7 -;@ stdcall EnumResourceNamesExW ; Win 7 @ stdcall EnumResourceNamesW(long wstr ptr long) @ stdcall EnumResourceTypesA(long ptr long) -;@ stdcall EnumResourceTypesExA ; Win 7 -;@ stdcall EnumResourceTypesExW ; Win 7 @ stdcall EnumResourceTypesW(long ptr long) @ stdcall EnumSystemCodePagesA(ptr long) @ stdcall EnumSystemCodePagesW(ptr long) -;@ stdcall EnumSystemFirmwareTables ; Win 7 +@ stdcall EnumSystemFirmwareTables(long ptr long) @ stdcall EnumSystemGeoID(long long ptr) @ stdcall EnumSystemLanguageGroupsA(ptr long ptr) @ stdcall EnumSystemLanguageGroupsW(ptr long ptr) @ stdcall EnumSystemLocalesA(ptr long) -;@ stdcall EnumSystemLocalesEx ; Win 7 @ stdcall EnumSystemLocalesW(ptr long) @ stdcall EnumTimeFormatsA(ptr long long) -;@ stdcall EnumTimeFormatsEx ; Win 7 @ stdcall EnumTimeFormatsW(ptr long long) @ stdcall EnumUILanguagesA(ptr long long) @ stdcall EnumUILanguagesW(ptr long long) @@ -302,7 +191,6 @@ @ stdcall ExpandEnvironmentStringsW(wstr ptr long) @ stdcall ExpungeConsoleCommandHistoryA(long) @ stdcall ExpungeConsoleCommandHistoryW(long) -@ stdcall ExtendVirtualBuffer(long long) ; missing in Win 7 @ stdcall FatalAppExitA(long str) @ stdcall FatalAppExitW(long wstr) @ stdcall FatalExit(long) @@ -324,24 +212,16 @@ @ stdcall FindFirstFileA(str ptr) @ stdcall FindFirstFileExA(str long ptr long ptr long) @ stdcall FindFirstFileExW(wstr long ptr long ptr long) -;@ stdcall FindFirstFileNameTransactedW ; Win 7 -;@ stdcall FindFirstFileNameW ; Win 7 -;@ stdcall FindFirstFileTransactedA ; Win 7 -;@ stdcall FindFirstFileTransactedW ; Win 7 @ stdcall FindFirstFileW(wstr ptr) -;@ stdcall FindFirstStreamTransactedW ; Win 7 @ stdcall FindFirstStreamW(wstr ptr ptr long) @ stdcall FindFirstVolumeA(ptr long) @ stdcall FindFirstVolumeMountPointA(str ptr long) @ stdcall FindFirstVolumeMountPointW(wstr ptr long) @ stdcall FindFirstVolumeW(ptr long) -;@ stdcall FindNLSString ; Win 7 -;@ stdcall FindNLSStringEx ; Win 7 @ stdcall FindNextChangeNotification(long) @ stdcall FindNextFileA(long ptr) -;@ stdcall FindNextFileNameW ; Win 7 @ stdcall FindNextFileW(long ptr) -;@ stdcall FindNextStreamW ; Win 7 +@ stdcall FindNextStreamW(ptr ptr) @ stdcall FindNextVolumeA(long ptr long) @ stdcall FindNextVolumeMountPointA(long str long) @ stdcall FindNextVolumeMountPointW(long wstr long) @@ -350,17 +230,15 @@ @ stdcall FindResourceExA(long str str long) @ stdcall FindResourceExW(long wstr wstr long) @ stdcall FindResourceW(long wstr wstr) -;@ stdcall FindStringOrdinal ; Win 7 @ stdcall FindVolumeClose(ptr) @ stdcall FindVolumeMountPointClose(ptr) -;@ stdcall FlsAlloc(ptr) ; missing in XP SP3 -;@ stdcall FlsFree(long) ; missing in XP SP3 -;@ stdcall FlsGetValue(long) ; missing in XP SP3 -;@ stdcall FlsSetValue(long ptr) ; missing in XP SP3 +;@ stdcall FlsAlloc(ptr) +;@ stdcall FlsFree(long) +;@ stdcall FlsGetValue(long) +;@ stdcall FlsSetValue(long ptr) @ stdcall FlushConsoleInputBuffer(long) @ stdcall FlushFileBuffers(long) @ stdcall FlushInstructionCache(long long long) -;@ stdcall FlushProcessWriteBuffers ntdll.NtFlushProcessWriteBuffers ; Win 7 @ stdcall FlushViewOfFile(ptr long) @ stdcall FoldStringA(long str long ptr long) @ stdcall FoldStringW(long wstr long ptr long) @@ -371,16 +249,10 @@ @ stdcall FreeEnvironmentStringsW(ptr) @ stdcall FreeLibrary(long) @ stdcall FreeLibraryAndExitThread(long long) -;@ stdcall FreeLibraryWhenCallbackReturns ntdll.TpCallbackUnloadDllOnCompletion ; Win 7 @ stdcall FreeResource(long) @ stdcall FreeUserPhysicalPages(long long long) -@ stdcall FreeVirtualBuffer(ptr) ; missing in Win 7 @ stdcall GenerateConsoleCtrlEvent(long long) @ stdcall GetACP() -;@ stdcall GetActiveProcessorCount ; Win 7 -;@ stdcall GetActiveProcessorGroupCount ; Win 7 -;@ stdcall GetApplicationRecoveryCallback ; Win 7 -;@ stdcall GetApplicationRestartSettings ; Win 7 @ stdcall GetAtomNameA(long ptr long) @ stdcall GetAtomNameW(long ptr long) @ stdcall GetBinaryType(str ptr) GetBinaryTypeA @@ -390,16 +262,8 @@ @ stdcall GetCPInfo(long ptr) @ stdcall GetCPInfoExA(long long ptr) @ stdcall GetCPInfoExW(long long ptr) -;@ stdcall GetCalendarDateFormat ; Win 7 -;@ stdcall GetCalendarDateFormatEx ; Win 7 -;@ stdcall GetCalendarDaysInMonth ; Win 7 -;@ stdcall GetCalendarDifferenceInDays ; Win 7 @ stdcall GetCalendarInfoA(long long long ptr long ptr) -;@ stdcall GetCalendarInfoEx ; Win 7 @ stdcall GetCalendarInfoW(long long long ptr long ptr) -;@ stdcall GetCalendarMonthsInYear ; Win 7 -;@ stdcall GetCalendarSupportedDateRange ; Win 7 -;@ stdcall GetCalendarWeekNumber ; Win 7 @ stdcall GetComPlusPackageInstallStatus() @ stdcall GetCommConfig(long ptr long) @ stdcall GetCommMask(long ptr) @@ -410,8 +274,6 @@ @ stdcall GetCommandLineA() @ stdcall GetCommandLineW() @ stdcall GetCompressedFileSizeA(long ptr) -;@ stdcall GetCompressedFileSizeTransactedA ; Win 7 -;@ stdcall GetCompressedFileSizeTransactedW ; Win 7 @ stdcall GetCompressedFileSizeW(long ptr) @ stdcall GetComputerNameA(ptr ptr) @ stdcall GetComputerNameExA(long ptr ptr) @@ -439,7 +301,6 @@ @ stdcall GetConsoleFontInfo(long long long ptr) @ stdcall GetConsoleFontSize(long long) @ stdcall GetConsoleHardwareState(long long ptr) -@ stdcall GetConsoleHistoryInfo(ptr) @ stdcall GetConsoleInputExeNameA(long ptr) @ stdcall GetConsoleInputExeNameW(long ptr) @ stdcall GetConsoleInputWaitHandle() @@ -447,35 +308,26 @@ @ stdcall GetConsoleKeyboardLayoutNameW(ptr) @ stdcall GetConsoleMode(long ptr) @ stdcall GetConsoleNlsMode(long ptr) -;@ stdcall GetConsoleOriginalTitleA ; Win 7 -;@ stdcall GetConsoleOriginalTitleW ; Win 7 @ stdcall GetConsoleOutputCP() @ stdcall GetConsoleProcessList(ptr long) ; missing in XP SP3 @ stdcall GetConsoleScreenBufferInfo(long ptr) -;@ stdcall GetConsoleScreenBufferInfoEx ; Win 7 @ stdcall GetConsoleSelectionInfo(ptr) @ stdcall GetConsoleTitleA(ptr long) @ stdcall GetConsoleTitleW(ptr long) @ stdcall GetConsoleWindow() @ stdcall GetCurrencyFormatA(long long str ptr str long) -;@ stdcall GetCurrencyFormatEx ; Win 7 @ stdcall GetCurrencyFormatW(long long str ptr str long) @ stdcall GetCurrentActCtx(ptr) @ stdcall GetCurrentConsoleFont(long long ptr) -;@ stdcall GetCurrentConsoleFontEx ; Win 7 @ stdcall GetCurrentDirectoryA(long ptr) @ stdcall GetCurrentDirectoryW(long ptr) @ stdcall GetCurrentProcess() @ stdcall GetCurrentProcessId() @ stdcall GetCurrentProcessorNumber() ntdll.RtlGetCurrentProcessorNumber -;@ stdcall GetCurrentProcessorNumberEx ntdll.RtlGetCurrentProcessorNumberEx ; Win 7 @ stdcall GetCurrentThread() @ stdcall GetCurrentThreadId() -;@ stdcall GetCurrentUmsThread @ stdcall GetDateFormatA(long long ptr str ptr long) -;@ stdcall GetDateFormatEx ; Win 7 @ stdcall GetDateFormatW(long long ptr wstr ptr long) -;@ stub GetDaylightFlag ; missing in XP SP3 and Win 7 @ stdcall GetDefaultCommConfigA(str ptr long) @ stdcall GetDefaultCommConfigW(wstr ptr long) @ stdcall GetDefaultSortkeySize(ptr) ; missing in Win 7 @@ -488,116 +340,70 @@ @ stdcall GetDllDirectoryW(long ptr) @ stdcall GetDriveTypeA(str) @ stdcall GetDriveTypeW(wstr) -;@ stdcall GetDurationFormat ; Win 7 -;@ stdcall GetDurationFormatEx ; Win 7 -;@ stdcall GetDynamicTimeZoneInformation ; Win 7 -;@ stdcall GetEnabledExtendedFeatures api-ms-win-core-xstate-l1-1-0.RtlGetEnabledExtendedFeatures ; Win 7 @ stdcall GetEnvironmentStrings() @ stdcall GetEnvironmentStringsA() GetEnvironmentStrings @ stdcall GetEnvironmentStringsW() @ stdcall GetEnvironmentVariableA(str ptr long) @ stdcall GetEnvironmentVariableW(wstr ptr long) -;@ stdcall GetEraNameCountedString ; Win 7 -@ stdcall GetErrorMode() @ stdcall GetExitCodeProcess(long ptr) @ stdcall GetExitCodeThread(long ptr) @ stdcall GetExpandedNameA(str ptr) @ stdcall GetExpandedNameW(wstr ptr) -;@ stdcall GetExtendedContextLength ; Win 7 -;@ stdcall GetExtendedFeaturesMask api-ms-win-core-xstate-l1-1-0.RtlGetExtendedFeaturesMask ; Win 7 @ stdcall GetFileAttributesA(str) -@ stdcall GetFileAttributesByHandle(long ptr long) ; missing in Win 7 @ stdcall GetFileAttributesExA(str long ptr) @ stdcall GetFileAttributesExW(wstr long ptr) -;@ stdcall GetFileAttributesTransactedA ; Win 7 -;@ stdcall GetFileAttributesTransactedW ; Win 7 @ stdcall GetFileAttributesW(wstr) -@ stdcall GetFileBandwidthReservation(long ptr ptr ptr ptr ptr) @ stdcall GetFileInformationByHandle(long ptr) -;@ stdcall GetFileInformationByHandleEx ; Win 7 -;@ stdcall GetFileMUIInfo ; Win 7 -;@ stdcall GetFileMUIPath ; Win 7 @ stdcall GetFileSize(long ptr) @ stdcall GetFileSizeEx(long ptr) @ stdcall GetFileTime(long ptr ptr ptr) @ stdcall GetFileType(long) -@ stdcall GetFinalPathNameByHandleA(long str long long) -@ stdcall GetFinalPathNameByHandleW(long wstr long long) @ stdcall GetFirmwareEnvironmentVariableA(str str ptr long) @ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long) @ stdcall GetFullPathNameA(str long ptr ptr) -;@ stdcall GetFullPathNameTransactedA ; Win 7 -;@ stdcall GetFullPathNameTransactedW ; Win 7 @ stdcall GetFullPathNameW(wstr long ptr ptr) @ stdcall GetGeoInfoA(long long ptr long long) @ stdcall GetGeoInfoW(long long ptr long long) @ stdcall GetHandleContext(long) ; missing on x64 @ stdcall GetHandleInformation(long ptr) -;@ stub GetSCallbackTarget ; missing in XP SP3 and Win 7 -;@ stub GetSCallbackTemplate ; missing in XP SP3 and Win 7 @ stdcall GetLargePageMinimum() @ stdcall GetLargestConsoleWindowSize(long) @ stdcall GetLastError() ntdll.RtlGetLastWin32Error @ stdcall GetLinguistLangSize(ptr) ; missing in Win 7 @ stdcall GetLocalTime(ptr) @ stdcall GetLocaleInfoA(long long ptr long) -@ stdcall GetLocaleInfoEx(wstr long wstr long) ; Vista+ @ stdcall GetLocaleInfoW(long long ptr long) @ stdcall GetLogicalDriveStringsA(long ptr) @ stdcall GetLogicalDriveStringsW(long ptr) @ stdcall GetLogicalDrives() @ stdcall GetLogicalProcessorInformation(ptr ptr) -;@ stdcall GetLogicalProcessorInformationEx api-ms-win-core-sysinfo-l1-1-0.GetLogicalProcessorInformationEx ; Win 7 @ stdcall GetLongPathNameA (str long long) -;@ stdcall GetLongPathNameTransactedA ; Win 7 -;@ stdcall GetLongPathNameTransactedW ; Win 7 @ stdcall GetLongPathNameW (wstr long long) @ stdcall GetMailslotInfo(long ptr ptr ptr ptr) -;@ stdcall GetMaximumProcessorCount ; Win 7 -;@ stdcall GetMaximumProcessorGroupCount ; Win 7 @ stdcall GetModuleFileNameA(long ptr long) @ stdcall GetModuleFileNameW(long ptr long) @ stdcall GetModuleHandleA(str) @ stdcall GetModuleHandleExA(long ptr ptr) @ stdcall GetModuleHandleExW(long ptr ptr) @ stdcall GetModuleHandleW(wstr) -;@ stdcall GetNLSVersion ; Win 7 -;@ stdcall GetNLSVersionEx ; Win 7 -;@ stdcall GetNamedPipeAttribute ; Win 7 -;@ stdcall GetNamedPipeClientComputerNameA ; Win 7 -;@ stdcall GetNamedPipeClientComputerNameW ; Win 7 -;@ stdcall GetNamedPipeClientProcessId ; Win 7 -;@ stdcall GetNamedPipeClientSessionId ; Win 7 +@ stdcall GetNLSVersion(long long ptr) @ stdcall GetNamedPipeHandleStateA(long ptr ptr ptr ptr str long) @ stdcall GetNamedPipeHandleStateW(long ptr ptr ptr ptr wstr long) @ stdcall GetNamedPipeInfo(long ptr ptr ptr ptr) -;@ stdcall GetNamedPipeServerProcessId ; Win 7 -;@ stdcall GetNamedPipeServerSessionId ; Win 7 @ stdcall GetNativeSystemInfo(ptr) -;@ stdcall -arch=x86_64 GetNextUmsListItem @ stdcall GetNextVDMCommand(long) @ stdcall GetNlsSectionName(long long long str str long) ; missing in Win 7 -@ stdcall GetNumaAvailableMemory(ptr long ptr) ; missing in Win 7 @ stdcall GetNumaAvailableMemoryNode(long ptr) -;@ stdcall GetNumaAvailableMemoryNodeEx ; Win 7 @ stdcall GetNumaHighestNodeNumber(ptr) -;@ stdcall GetNumaNodeNumberFromHandle ; Win 7 @ stdcall GetNumaNodeProcessorMask(long ptr) -;@ stdcall GetNumaNodeProcessorMaskEx ; Win 7 -@ stdcall GetNumaProcessorMap(ptr long ptr) ; missing in Win 7 @ stdcall GetNumaProcessorNode(long ptr) -;@ stdcall GetNumaProcessorNodeEx ; Win 7 -;@ stdcall GetNumaProximityNode ; Win 7 -;@ stdcall GetNumaProximityNodeEx ; Win 7 @ stdcall GetNumberFormatA(long long str ptr ptr long) -;@ stdcall GetNumberFormatEx ; Win 7 @ stdcall GetNumberFormatW(long long wstr ptr ptr long) @ stdcall GetNumberOfConsoleFonts() @ stdcall GetNumberOfConsoleInputEvents(long ptr) @ stdcall GetNumberOfConsoleMouseButtons(ptr) @ stdcall GetOEMCP() @ stdcall GetOverlappedResult(long ptr ptr long) -;@ stdcall GetPhysicallyInstalledSystemMemory ; Win 7 @ stdcall GetPriorityClass(long) @ stdcall GetPrivateProfileIntA(str str long str) @ stdcall GetPrivateProfileIntW(wstr wstr long wstr) @@ -611,25 +417,18 @@ @ stdcall GetPrivateProfileStructW(wstr wstr ptr long wstr) @ stdcall GetProcAddress(long str) @ stdcall GetProcessAffinityMask(long ptr ptr) -;@ stdcall GetProcessFlags(long) -;@ stdcall GetProcessDEPPolicy ; Win 7 -;@ stdcall GetProcessGroupAffinity ; Win 7 @ stdcall GetProcessHandleCount(long ptr) @ stdcall GetProcessHeap() @ stdcall GetProcessHeaps(long ptr) @ stdcall GetProcessId(long) -;@ stdcall GetProcessIdOfThread ; Win 7 +@ stdcall GetProcessIdOfThread(ptr) @ stdcall GetProcessIoCounters(long ptr) -;@ stdcall GetProcessPreferredUILanguages ; Win 7 @ stdcall GetProcessPriorityBoost(long ptr) @ stdcall GetProcessShutdownParameters(ptr ptr) @ stdcall GetProcessTimes(long ptr ptr ptr ptr) @ stdcall GetProcessVersion(long) @ stdcall GetProcessWorkingSetSize(long ptr ptr) -;@ stdcall GetProcessWorkingSetSizeEx ; Win 7 -;@ stdcall GetProcessorSystemCycleTime ; Win 7 -;@ stdcall GetProductInfo(long long long long ptr) ; Win 7 -;@ stub GetProductName +@ stdcall GetProcessWorkingSetSizeEx(long ptr ptr long) @ stdcall GetProfileIntA(str str long) @ stdcall GetProfileIntW(wstr wstr long) @ stdcall GetProfileSectionA(str ptr long) @@ -637,31 +436,24 @@ @ stdcall GetProfileStringA(str str str ptr long) @ stdcall GetProfileStringW(wstr wstr wstr ptr long) @ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) -;@ stdcall GetQueuedCompletionStatusEx ; Win 7 -;@ stub GetLSCallbackTarget ; missing in XP SP3 and Win 7 -;@ stub GetLSCallbackTemplate ; missing in XP SP3 and Win 7 @ stdcall GetShortPathNameA(str ptr long) @ stdcall GetShortPathNameW(wstr ptr long) @ stdcall GetStartupInfoA(ptr) @ stdcall GetStartupInfoW(ptr) @ stdcall GetStdHandle(long) -;@ stdcall GetStringScripts ; Win 7 @ stdcall GetStringTypeA(long long str long ptr) @ stdcall GetStringTypeExA(long long str long ptr) @ stdcall GetStringTypeExW(long long wstr long ptr) @ stdcall GetStringTypeW(long wstr long ptr) -;@ stdcall GetSystemDEPPolicy ; Win 7 @ stdcall GetSystemDefaultLCID() @ stdcall GetSystemDefaultLangID() -;@ stdcall GetSystemDefaultLocaleName ; Win 7 @ stdcall GetSystemDefaultUILanguage() @ stdcall GetSystemDirectoryA(ptr long) @ stdcall GetSystemDirectoryW(ptr long) -;@ stdcall GetSystemFileCacheSize ; Win 7 -;@ stdcall GetSystemFirmwareTable ; Win 7 +@ stdcall GetSystemFileCacheSize(ptr ptr ptr) +@ stdcall GetSystemFirmwareTable(long long ptr long) @ stdcall GetSystemInfo(ptr) @ stdcall GetSystemPowerStatus(ptr) -;@ stdcall GetSystemPreferredUILanguages ; Win 7 @ stdcall GetSystemRegistryQuota(ptr ptr) @ stdcall GetSystemTime(ptr) @ stdcall GetSystemTimeAdjustment(ptr ptr ptr) @@ -679,39 +471,26 @@ @ stdcall GetTempPathA(long ptr) @ stdcall GetTempPathW(long ptr) @ stdcall GetThreadContext(long ptr) -;@ stdcall GetThreadErrorMode() ; Win 7 -;@ stdcall GetThreadGroupAffinity ; Win 7 @ stdcall GetThreadIOPendingFlag(long ptr) @ stdcall GetThreadId(ptr) -;@ stdcall GetThreadIdealProcessorEx ; Win 7 @ stdcall GetThreadLocale() -;@ stdcall GetThreadPreferredUILanguages ; Win 7 @ stdcall GetThreadPriority(long) @ stdcall GetThreadPriorityBoost(long ptr) @ stdcall GetThreadSelectorEntry(long long ptr) @ stdcall GetThreadTimes(long ptr ptr ptr ptr) -;@ stdcall GetThreadUILanguage ; Win 7 @ stdcall GetTickCount() -@ stdcall -ret64 GetTickCount64() @ stdcall GetTimeFormatA(long long ptr str ptr long) -;@ stdcall GetTimeFormatEx ; Win 7 @ stdcall GetTimeFormatW(long long ptr wstr ptr long) @ stdcall GetTimeZoneInformation(ptr) -;@ stdcall GetTimeZoneInformationForYear ; Win 7 -;@ stdcall GetUILanguageInfo ; Win 7 -;@ stdcall -arch=x86_64 GetUmsCompletionListEvent @ stdcall GetUserDefaultLCID() @ stdcall GetUserDefaultLangID() -;@ stdcall GetUserDefaultLocaleName ; Win 7 @ stdcall GetUserDefaultUILanguage() @ stdcall GetUserGeoID(long) -;@ stdcall GetUserPreferredUILanguages ; Win 7 @ stdcall GetVDMCurrentDirectories(long long) @ stdcall GetVersion() @ stdcall GetVersionExA(ptr) @ stdcall GetVersionExW(ptr) @ stdcall GetVolumeInformationA(str ptr long ptr ptr ptr ptr long) -;@ stdcall GetVolumeInformationByHandleW ; Win 7 @ stdcall GetVolumeInformationW(wstr ptr long ptr ptr ptr ptr long) @ stdcall GetVolumeNameForVolumeMountPointA(str ptr long) @ stdcall GetVolumeNameForVolumeMountPointW(wstr ptr long) @@ -759,7 +538,6 @@ @ stdcall HeapQueryInformation(long long ptr long ptr) @ stdcall HeapQueryTagW(long long long long ptr) ; missing in Win 7 @ stdcall HeapReAlloc(long long ptr long) ntdll.RtlReAllocateHeap -;@ stub HeapSetFlags ; missing in XP SP3 and Win 7 @ stdcall HeapSetInformation(ptr long ptr long) @ stdcall HeapSize(long long ptr) ntdll.RtlSizeHeap @ stdcall HeapSummary(long long ptr) @@ -767,34 +545,20 @@ @ stdcall HeapUsage(long long long long ptr) ; missing in Win 7 @ stdcall HeapValidate(long long ptr) @ stdcall HeapWalk(long ptr) -;@ stdcall IdnToAscii ; Win 7 -;@ stdcall IdnToNameprepUnicode ; Win 7 -;@ stdcall IdnToUnicode ; Win 7 @ stdcall InitAtomTable(long) -;@ stdcall InitOnceBeginInitialize ; Win 7 -;@ stdcall InitOnceComplete ; Win 7 -;@ stdcall InitOnceExecuteOnce ; Win 7 -;@ stdcall InitOnceInitialize ntdll.RtlRunOnceInitialize ; Win 7 -;@ stdcall InitializeConditionVariable ntdll.RtlInitializeConditionVariable ; Win 7 -@ stdcall InitializeCriticalSection(ptr) ; FIXME: ntdll.RtlInitializeCriticalSection +@ stdcall InitializeCriticalSection(ptr) @ stdcall InitializeCriticalSectionAndSpinCount(ptr long) -@ stdcall InitializeCriticalSectionEx(ptr long long) -;@ stdcall InitializeExtendedContext ; Win 7 -;@ stdcall InitializeProcThreadAttributeList api-ms-win-core-processthreads-l1-1-0.InitializeProcThreadAttributeList ; Win 7 @ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead -@ stdcall InitializeSRWLock(ptr) ntdll.RtlInitializeSRWLock +@ stdcall -arch=i386 -ret64 InterlockedCompareExchange64(ptr double double) ntdll.RtlInterlockedCompareExchange64 @ stdcall -arch=i386 InterlockedCompareExchange (ptr long long) -;@ stdcall -arch=i386 -ret64 InterlockedCompareExchange64(ptr double double) ntdll.RtlInterlockedCompareExchange64 @ stdcall -arch=i386 InterlockedDecrement(ptr) @ stdcall -arch=i386 InterlockedExchange(ptr long) -@ stdcall -arch=i386 InterlockedExchangeAdd (ptr long ) +@ stdcall -arch=i386 InterlockedExchangeAdd(ptr long) @ stdcall InterlockedFlushSList(ptr) ntdll.RtlInterlockedFlushSList @ stdcall -arch=i386 InterlockedIncrement(ptr) @ stdcall InterlockedPopEntrySList(ptr) ntdll.RtlInterlockedPopEntrySList @ stdcall InterlockedPushEntrySList(ptr ptr) ntdll.RtlInterlockedPushEntrySList -;@ stdcall InterlockedPushListSList ntdll.RtlInterlockedPushListSList ; Win 7 @ stdcall InvalidateConsoleDIBits(long long) -;@ stub InvalidateNSCache ; missing in XP SP3 and Win 7 @ stdcall IsBadCodePtr(ptr) @ stdcall IsBadHugeReadPtr(ptr long) @ stdcall IsBadHugeWritePtr(ptr long) @@ -802,63 +566,25 @@ @ stdcall IsBadStringPtrA(ptr long) @ stdcall IsBadStringPtrW(ptr long) @ stdcall IsBadWritePtr(ptr long) -;@ stdcall IsCalendarLeapDay ; Win 7 -;@ stdcall IsCalendarLeapMonth ; Win 7 -;@ stdcall IsCalendarLeapYear ; Win 7 @ stdcall IsDBCSLeadByte(long) @ stdcall IsDBCSLeadByteEx(long long) @ stdcall IsDebuggerPresent() -;@ stdcall IsNLSDefinedString ; Win 7 -;@ stdcall IsNormalizedString ; Win 7 +@ stdcall IsNLSDefinedString(long long ptr long long) @ stdcall IsProcessInJob(long long ptr) @ stdcall IsProcessorFeaturePresent(long) @ stdcall IsSystemResumeAutomatic() -@ stdcall IsThreadAFiber() -;@ stdcall IsThreadAFiber ; Win 7 -;@ stdcall IsThreadpoolTimerSet ntdll.TpIsTimerSet ; Win 7 -;@ stdcall IsTimeZoneRedirectionEnabled ; Win 7 -;@ stdcall IsValidCalDateTime ; Win 7 +@ stdcall IsTimeZoneRedirectionEnabled() @ stdcall IsValidCodePage(long) @ stdcall IsValidLanguageGroup(long long) @ stdcall IsValidLocale(long long) -;@ stdcall IsValidLocaleName ; Win 7 @ stdcall IsValidUILanguage(long) ; missing in Win 7 @ stdcall IsWow64Process(ptr ptr) -;@ stdcall K32EmptyWorkingSet ; Win 7 -;@ stdcall K32EnumDeviceDrivers ; Win 7 -;@ stdcall K32EnumPageFilesA ; Win 7 -;@ stdcall K32EnumPageFilesW ; Win 7 -;@ stdcall K32EnumProcessModules ; Win 7 -;@ stdcall K32EnumProcessModulesEx ; Win 7 -;@ stdcall K32EnumProcesses ; Win 7 -;@ stdcall K32GetDeviceDriverBaseNameA ; Win 7 -;@ stdcall K32GetDeviceDriverBaseNameW ; Win 7 -;@ stdcall K32GetDeviceDriverFileNameA ; Win 7 -;@ stdcall K32GetDeviceDriverFileNameW ; Win 7 -;@ stdcall K32GetMappedFileNameA ; Win 7 -;@ stdcall K32GetMappedFileNameW ; Win 7 -;@ stdcall K32GetModuleBaseNameA ; Win 7 -;@ stdcall K32GetModuleBaseNameW ; Win 7 -;@ stdcall K32GetModuleFileNameExA ; Win 7 -;@ stdcall K32GetModuleFileNameExW ; Win 7 -;@ stdcall K32GetModuleInformation ; Win 7 -;@ stdcall K32GetPerformanceInfo ; Win 7 -;@ stdcall K32GetProcessImageFileNameA ; Win 7 -;@ stdcall K32GetProcessImageFileNameW ; Win 7 -;@ stdcall K32GetProcessMemoryInfo ; Win 7 -;@ stdcall K32GetWsChanges ; Win 7 -;@ stdcall K32GetWsChangesEx ; Win 7 -;@ stdcall K32InitializeProcessForWsWatch ; Win 7 -;@ stdcall K32QueryWorkingSet ; Win 7 -;@ stdcall K32QueryWorkingSetEx ; Win 7 -@ stdcall LCIDToLocaleName(long wstr long long) ; needed for wine gecko; missing in XP SP3 @ stdcall LCMapStringA(long long str long ptr long) -;@ stdcall LCMapStringEx ; Win 7 @ stdcall LCMapStringW(long long wstr long ptr long) @ stdcall LZClose(long) -;@ stdcall LZCloseFile ; Win 7 +@ stdcall LZCloseFile(long) @ stdcall LZCopy(long long) -;@ stdcall LZCreateFileW ; Win 7 +@ stdcall LZCreateFileW(ptr long long long ptr) @ stdcall LZDone() @ stdcall LZInit(long) @ stdcall LZOpenFileA(str ptr long) @@ -867,16 +593,12 @@ @ stdcall LZSeek(long long long) @ stdcall LZStart() @ stdcall LeaveCriticalSection(ptr) ntdll.RtlLeaveCriticalSection -;@ stdcall LeaveCriticalSectionWhenCallbackReturns ntdll.TpCallbackLeaveCriticalSectionOnCompletion ; Win 7 -;@ stdcall LoadAppInitDlls ; Win 7 @ stdcall LoadLibraryA(str) @ stdcall LoadLibraryExA( str long long) @ stdcall LoadLibraryExW(wstr long long) @ stdcall LoadLibraryW(wstr) @ stdcall LoadModule(str ptr) @ stdcall LoadResource(long long) -;@ stdcall LoadStringBaseExW ; Win 7 -;@ stdcall LoadStringBaseW ; Win 7 @ stdcall LocalAlloc(long long) @ stdcall LocalCompact(long) @ stdcall LocalFileTimeToFileTime(ptr ptr) @@ -888,18 +610,13 @@ @ stdcall LocalShrink(long long) @ stdcall LocalSize(long) @ stdcall LocalUnlock(long) -;@ stub LocaleNameToLCID ; missing in XP SP3 -;@ stdcall LocateExtendedFeature api-ms-win-core-xstate-l1-1-0.RtlLocateExtendedFeature ; Win 7 -;@ stdcall LocateLegacyContext api-ms-win-core-xstate-l1-1-0.RtlLocateLegacyContext ; Win 7 @ stdcall LockFile(long long long long long) @ stdcall LockFileEx(long long long long long ptr) @ stdcall LockResource(long) -;@ stdcall MakeCriticalSectionGlobal(ptr) // ??? @ stdcall MapUserPhysicalPages(ptr long ptr) @ stdcall MapUserPhysicalPagesScatter(ptr long ptr) @ stdcall MapViewOfFile(long long long long long) @ stdcall MapViewOfFileEx(long long long long long ptr) -;@ stdcall MapViewOfFileExNuma ; Win 7 @ stdcall Module32First(long ptr) @ stdcall Module32FirstW(long ptr) @ stdcall Module32Next(long ptr) @@ -907,8 +624,6 @@ @ stdcall MoveFileA(str str) @ stdcall MoveFileExA(str str long) @ stdcall MoveFileExW(wstr wstr long) -;@ stdcall MoveFileTransactedA ; Win 7 -;@ stdcall MoveFileTransactedW ; Win 7 @ stdcall MoveFileW(wstr wstr) @ stdcall MoveFileWithProgressA(str str ptr ptr long) @ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long) @@ -916,40 +631,25 @@ @ stdcall MultiByteToWideChar(long long str long ptr long) @ stdcall NeedCurrentDirectoryForExePathA(str) @ stdcall NeedCurrentDirectoryForExePathW(wstr) -;@ stdcall NlsCheckPolicy ; Win 7 @ stdcall NlsConvertIntegerToString(long long long wstr long) ; missing in Win 7 -;@ stdcall NlsEventDataDescCreate ; Win 7 @ stdcall NlsGetCacheUpdateCount() -;@ stub NlsResetProcessLocale ; missing in XP SP3 and Win 7 -;@ stdcall NlsUpdateLocale ; Win 7 -;@ stdcall NlsUpdateSystemLocale ; Win 7 -;@ stdcall NlsWriteEtwEvent ; Win 7 -;@ stdcall NormalizeString ; Win 7 -;@ stdcall NotifyMountMgr ; Win 7 -;@ stub NotifyNLSUserCache ; missing in XP SP3 and win 7 -;@ stdcall NotifyUILanguageChange ; Win 7 -@ stdcall NumaVirtualQueryNode(long long long long) ; missing in win 7 +@ stdcall NlsResetProcessLocale() @ stdcall OpenConsoleW(wstr long long long) @ stdcall OpenDataFile(long long) ; missing in Win 7 @ stdcall OpenEventA(long long str) @ stdcall OpenEventW(long long wstr) @ stdcall OpenFile(str ptr long) -;@ stdcall OpenFileById ; Win 7 @ stdcall OpenFileMappingA(long long str) @ stdcall OpenFileMappingW(long long wstr) @ stdcall OpenJobObjectA(long long str) @ stdcall OpenJobObjectW(long long wstr) @ stdcall OpenMutexA(long long str) @ stdcall OpenMutexW(long long wstr) -;@ stdcall OpenPrivateNamespaceA ; Win 7 -;@ stdcall OpenPrivateNamespaceW ; Win 7 @ stdcall OpenProcess(long long long) -;@ stdcall OpenProcessToken api-ms-win-core-processthreads-l1-1-0.OpenProcessToken ; Win 7 @ stdcall OpenProfileUserMapping() @ stdcall OpenSemaphoreA(long long str) @ stdcall OpenSemaphoreW(long long wstr) @ stdcall OpenThread(long long long) -;@ stdcall OpenThreadToken api-ms-win-core-processthreads-l1-1-0.OpenThreadToken ; win 7 @ stdcall OpenWaitableTimerA(long long str) @ stdcall OpenWaitableTimerW(long long wstr) @ stdcall OutputDebugStringA(str) @@ -958,9 +658,6 @@ @ stdcall PeekConsoleInputW(ptr ptr long ptr) @ stdcall PeekNamedPipe(long ptr long ptr ptr ptr) @ stdcall PostQueuedCompletionStatus(long long ptr ptr) -;@ stdcall PowerClearRequest ; Win 7 -;@ stdcall PowerCreateRequest ; Win 7 -;@ stdcall PowerSetRequest ; Win 7 @ stdcall PrepareTape(ptr long long) @ stdcall PrivCopyFileExW(wstr wstr ptr ptr long long) @ stdcall PrivMoveFileIdentityW(long long long) @@ -971,34 +668,17 @@ @ stdcall ProcessIdToSessionId(long ptr) @ stdcall PulseEvent(long) @ stdcall PurgeComm(long long) -;@ stdcall QueryActCtxSettingsW ; Win 7 -;@ stdcall QueryActCtxW(long ptr ptr long ptr long ptr) @ stdcall QueryActCtxW(long ptr ptr long ptr long ptr) @ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList @ stdcall QueryDosDeviceA(str ptr long) @ stdcall QueryDosDeviceW(wstr ptr long) -@ stdcall QueryFullProcessImageNameA(ptr long str ptr) ; Vista and later -@ stdcall QueryFullProcessImageNameW(ptr long wstr ptr) ; Vista and later -;@ stdcall QueryIdleProcessorCycleTime ; Win 7 -;@ stdcall QueryIdleProcessorCycleTimeEx ; Win 7 @ stdcall QueryInformationJobObject(long long ptr long ptr) @ stdcall QueryMemoryResourceNotification(ptr ptr) -;@ stub QueryNumberOfEventLogRecords ; missing in XP SP3 and Win 7 -;@ stub QueryOldestEventLogRecord ; missing in XP SP3 and Win 7 @ stdcall QueryPerformanceCounter(ptr) @ stdcall QueryPerformanceFrequency(ptr) -;@ stdcall QueryProcessAffinityUpdateMode ; Win 7 -;@ stdcall QueryProcessCycleTime ; Win 7 -;@ stdcall QueryThreadCycleTime ; Win 7 -;@ stdcall QueryThreadProfiling ; Win 7 -;@ stdcall QueryThreadpoolStackInformation ; Win 7 -;@ stdcall -arch=x86_64 QueryUmsThreadInformation -;@ stdcall QueryUnbiasedInterruptTime ; Win 7 -@ stdcall QueryWin31IniFilesMappedToRegistry(long long long long) ; missing in Win 7 @ stdcall QueueUserAPC(ptr long long) @ stdcall QueueUserWorkItem(ptr ptr long) @ stdcall RaiseException(long long long ptr) -;@ stdcall RaiseFailFastException ; Win 7 @ stdcall ReOpenFile(ptr long long long) @ stdcall ReadConsoleA(long ptr long ptr ptr) @ stdcall ReadConsoleInputA(long ptr long ptr) @@ -1016,105 +696,37 @@ @ stdcall ReadFileEx(long ptr long ptr ptr) @ stdcall ReadFileScatter(long ptr long ptr ptr) @ stdcall ReadProcessMemory(long ptr ptr long ptr) -;@ stdcall ReadThreadProfilingData ; Win 7 -;@ stdcall RegCloseKey ; Win 7 -;@ stdcall RegCreateKeyExA ; Win 7 -;@ stdcall RegCreateKeyExW ; Win 7 -;@ stdcall RegDeleteKeyExA ; Win 7 -;@ stdcall RegDeleteKeyExW ; Win 7 -;@ stdcall RegDeleteTreeA ; Win 7 -;@ stdcall RegDeleteTreeW ; Win 7 -;@ stdcall RegDeleteValueA ; Win 7 -;@ stdcall RegDeleteValueW ; Win 7 -;@ stdcall RegDisablePredefinedCacheEx ; Win 7 -;@ stdcall RegEnumKeyExA ; Win 7 -;@ stdcall RegEnumKeyExW ; Win 7 -;@ stdcall RegEnumValueA ; Win 7 -;@ stdcall RegEnumValueW ; Win 7 -;@ stdcall RegFlushKey ; Win 7 -;@ stdcall RegGetKeySecurity ; Win 7 -;@ stdcall RegGetValueA ; Win 7 -;@ stdcall RegGetValueW ; Win 7 -;@ stdcall RegKrnGetGlobalState ; Win 7 -;@ stdcall RegKrnInitialize ; Win 7 -;@ stdcall RegLoadKeyA ; Win 7 -;@ stdcall RegLoadKeyW ; Win 7 -;@ stdcall RegLoadMUIStringA ; Win 7 -;@ stdcall RegLoadMUIStringW ; Win 7 -;@ stdcall RegNotifyChangeKeyValue ; Win 7 -;@ stdcall RegOpenCurrentUser ; Win 7 -;@ stdcall RegOpenKeyExA ; Win 7 -;@ stdcall RegOpenKeyExW ; Win 7 -;@ stdcall RegOpenUserClassesRoot ; Win 7 -;@ stdcall RegQueryInfoKeyA ; Win 7 -;@ stdcall RegQueryInfoKeyW ; Win 7 -;@ stdcall RegQueryValueExA ; Win 7 -;@ stdcall RegQueryValueExW ; Win 7 -;@ stdcall RegRestoreKeyA ; Win 7 -;@ stdcall RegRestoreKeyW ; Win 7 -;@ stdcall RegSaveKeyExA ; Win 7 -;@ stdcall RegSaveKeyExW ; Win 7 -;@ stdcall RegSetKeySecurity ; Win 7 -;@ stdcall RegSetValueExA ; Win 7 -;@ stdcall RegSetValueExW ; Win 7 -;@ stdcall RegUnLoadKeyA ; Win 7 -;@ stdcall RegUnLoadKeyW ; Win 7 -;@ stdcall RegisterApplicationRecoveryCallback ; Win 7 -@ stdcall RegisterApplicationRestart(wstr long) @ stdcall RegisterConsoleIME(ptr ptr) @ stdcall RegisterConsoleOS2(long) @ stdcall RegisterConsoleVDM(long long long long long long long long long long long) -;@ stub RegisterServiceProcess ; missing in XP SP3 and Win 7 -;@ stub RegisterSysMsgHandler ; missing in XP SP3 and win 7 @ stdcall RegisterWaitForInputIdle(ptr) @ stdcall RegisterWaitForSingleObject(ptr long ptr ptr long long) @ stdcall RegisterWaitForSingleObjectEx(long ptr ptr long long) @ stdcall RegisterWowBaseHandlers(long) @ stdcall RegisterWowExec(long) -;@ stdcall ReinitializeCriticalSection(ptr) ; ??? @ stdcall ReleaseActCtx(ptr) @ stdcall ReleaseMutex(long) -;@ stdcall ReleaseMutexWhenCallbackReturns ntdll.TpCallbackReleaseMutexOnCompletion ; Win 7 -@ stdcall ReleaseSRWLockExclusive(ptr) ntdll.RtlReleaseSRWLockExclusive -@ stdcall ReleaseSRWLockShared(ptr) ntdll.RtlReleaseSRWLockShared @ stdcall ReleaseSemaphore(long long ptr) -;@ stdcall ReleaseSemaphoreWhenCallbackReturns ntdll.TpCallbackReleaseSemaphoreOnCompletion ; Win 7 @ stdcall RemoveDirectoryA(str) -;@ stdcall RemoveDirectoryTransactedA ; Win 7 -;@ stdcall RemoveDirectoryTransactedW ; Win 7 @ stdcall RemoveDirectoryW(wstr) @ stdcall RemoveLocalAlternateComputerNameA(str long) @ stdcall RemoveLocalAlternateComputerNameW(wstr long) -;@ stdcall RemoveSecureMemoryCacheCallback ; Win 7 @ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler @ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler @ stdcall ReplaceFile(wstr wstr wstr long ptr ptr) ReplaceFileW @ stdcall ReplaceFileA(str str str long ptr ptr) @ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr) -;@ stdcall ReplacePartitionUnit ; Win 7 @ stdcall RequestDeviceWakeup(long) @ stdcall RequestWakeupLatency(long) @ stdcall ResetEvent(long) @ stdcall ResetWriteWatch(ptr long) -;@ stdcall ResolveLocaleName ; Win 7 @ stdcall RestoreLastError(long) ntdll.RtlRestoreLastWin32Error @ stdcall ResumeThread(long) -@ cdecl -arch=x86_64 RtlAddFunctionTable(ptr long long) ntdll.RtlAddFunctionTable @ stdcall -register RtlCaptureContext(ptr) ntdll.RtlCaptureContext @ stdcall RtlCaptureStackBackTrace(long long ptr ptr) ntdll.RtlCaptureStackBackTrace -@ stdcall -arch=x86_64 RtlCompareMemory(ptr ptr ptr) -@ stdcall -arch=x86_64 RtlCopyMemory(ptr ptr ptr) -@ stdcall -arch=x86_64 RtlDeleteFunctionTable(ptr) @ stdcall RtlFillMemory(ptr long long) ntdll.RtlFillMemory -@ stdcall -arch=x86_64 RtlInstallFunctionTableCallback(double double long ptr ptr ptr) -@ stdcall -arch=x86_64 RtlLookupFunctionEntry(ptr ptr ptr) ntdll.RtlLookupFunctionEntry @ stdcall RtlMoveMemory(ptr ptr long) ntdll.RtlMoveMemory -@ stdcall -arch=x86_64 RtlPcToFileHeader(ptr ptr) ntdll.RtlPcToFileHeader -@ stdcall -arch=x86_64 RtlRaiseException(ptr) ntdll.RtlRaiseException -@ stdcall -arch=x86_64 RtlRestoreContext(ptr ptr) ntdll.RtlRestoreContext @ stdcall RtlUnwind(ptr ptr ptr long) ntdll.RtlUnwind -@ stdcall -arch=x86_64 RtlUnwindEx(ptr ptr ptr ptr ptr ptr) ntdll.RtlUnwindEx -@ stdcall -arch=x86_64 RtlVirtualUnwind(ptr ptr ptr long) ntdll.RtlVirtualUnwind @ stdcall RtlZeroMemory(ptr long) ntdll.RtlZeroMemory @ stdcall ScrollConsoleScreenBufferA(long ptr ptr ptr ptr) @ stdcall ScrollConsoleScreenBufferW(long ptr ptr ptr ptr) @@ -1145,7 +757,6 @@ @ stdcall SetConsoleDisplayMode(long long ptr) @ stdcall SetConsoleFont(long long) @ stdcall SetConsoleHardwareState(long long long) -@ stdcall SetConsoleHistoryInfo(ptr) @ stdcall SetConsoleIcon(ptr) @ stdcall SetConsoleInputExeNameA(ptr) @ stdcall SetConsoleInputExeNameW(ptr) @@ -1160,41 +771,29 @@ @ stdcall SetConsoleOS2OemFormat(long) @ stdcall SetConsoleOutputCP(long) @ stdcall SetConsolePalette(long long long) -;@ stdcall SetConsoleScreenBufferInfoEx ; Win 7 @ stdcall SetConsoleScreenBufferSize(long long) @ stdcall SetConsoleTextAttribute(long long) @ stdcall SetConsoleTitleA(str) @ stdcall SetConsoleTitleW(wstr) @ stdcall SetConsoleWindowInfo(long long ptr) @ stdcall SetCriticalSectionSpinCount(ptr long) ntdll.RtlSetCriticalSectionSpinCount -;@ stdcall SetCurrentConsoleFontEx ; Win 7 @ stdcall SetCurrentDirectoryA(str) @ stdcall SetCurrentDirectoryW(wstr) -;@ stub SetDaylightFlag ; missing in XP SP3 and Win 7 @ stdcall SetDefaultCommConfigA(str ptr long) @ stdcall SetDefaultCommConfigW(wstr ptr long) @ stdcall SetDllDirectoryA(str) @ stdcall SetDllDirectoryW(wstr) -;@ stdcall SetDynamicTimeZoneInformation ; Win 7 @ stdcall SetEndOfFile(long) -;@ stdcall SetEnvironmentStringsA ; Win 7 -;@ stdcall SetEnvironmentStringsW ; Win 7 +@ stdcall SetEnvironmentStringsA(ptr) +@ stdcall SetEnvironmentStringsW(ptr) @ stdcall SetEnvironmentVariableA(str str) @ stdcall SetEnvironmentVariableW(wstr wstr) @ stdcall SetErrorMode(long) @ stdcall SetEvent(long) -;@ stdcall SetEventWhenCallbackReturns ntdll.TpCallbackSetEventOnCompletion ; Win 7 -;@ stdcall SetExtendedFeaturesMask api-ms-win-core-xstate-l1-1-0.RtlSetExtendedFeaturesMask ; Win 7 @ stdcall SetFileApisToANSI() @ stdcall SetFileApisToOEM() @ stdcall SetFileAttributesA(str long) -;@ stdcall SetFileAttributesTransactedA ; Win 7 -;@ stdcall SetFileAttributesTransactedW ; Win 7 @ stdcall SetFileAttributesW(wstr long) -;@ stdcall SetFileBandwidthReservation ; Win 7 -;@ stdcall SetFileCompletionNotificationModes ; Win 7 -;@ stdcall SetFileInformationByHandle ; Win 7 -;@ stdcall SetFileIoOverlappedRange ; Win 7 @ stdcall SetFilePointer(long long ptr long) @ stdcall SetFilePointerEx(long double ptr long) @ stdcall SetFileShortNameA(long str) @@ -1216,21 +815,15 @@ @ stdcall SetLocaleInfoW(long long wstr) @ stdcall SetMailslotInfo(long long) @ stdcall SetMessageWaitingIndicator(ptr long) -;@ stdcall SetNamedPipeAttribute ; Win 7 @ stdcall SetNamedPipeHandleState(long ptr ptr ptr) @ stdcall SetPriorityClass(long long) @ stdcall SetProcessAffinityMask(long long) -;@ stdcall SetProcessAffinityUpdateMode ; Win 7 -;@ stdcall SetProcessDEPPolicy ; Win 7 -;@ stdcall SetProcessPreferredUILanguages ; Win 7 @ stdcall SetProcessPriorityBoost(long long) @ stdcall SetProcessShutdownParameters(long long) @ stdcall SetProcessWorkingSetSize(long long long) -;@ stdcall SetProcessWorkingSetSizeEx ; Win 7 -;@ stdcall SetSearchPathMode ; Win 7 +@ stdcall SetProcessWorkingSetSizeEx(long long long long) @ stdcall SetStdHandle(long long) -;@ stdcall SetStdHandleEx ; Win 7 -;@ stdcall SetSystemFileCacheSize ; Win 7 +@ stdcall SetSystemFileCacheSize(long long long) @ stdcall SetSystemPowerState(long long) @ stdcall SetSystemTime(ptr) @ stdcall SetSystemTimeAdjustment(long long) @@ -1239,26 +832,15 @@ @ stdcall SetTermsrvAppInstallMode(long) @ stdcall SetThreadAffinityMask(long long) @ stdcall SetThreadContext(long ptr) -;@ stdcall SetThreadErrorMode(long ptr) ; Win 7 @ stdcall SetThreadExecutionState(long) -;@ stdcall SetThreadGroupAffinity ; Win 7 @ stdcall SetThreadIdealProcessor(long long) -;@ stdcall SetThreadIdealProcessorEx ; Win 7 @ stdcall SetThreadLocale(long) -;@ stdcall SetThreadPreferredUILanguages ; Win 7 @ stdcall SetThreadPriority(long long) @ stdcall SetThreadPriorityBoost(long long) -;@ stdcall SetThreadStackGuarantee ; Win 7 -;@ stdcall SetThreadToken api-ms-win-core-processthreads-l1-1-0.SetThreadToken ; Win 7 +@ stdcall SetThreadStackGuarantee(ptr) @ stdcall SetThreadUILanguage(long) -;@ stdcall SetThreadpoolStackInformation ; Win 7 -;@ stdcall SetThreadpoolThreadMaximum ntdll.TpSetPoolMaxThreads ; Win 7 -;@ stdcall SetThreadpoolThreadMinimum ; Win 7 -;@ stdcall SetThreadpoolTimer ntdll.TpSetTimer ; Win 7 -;@ stdcall SetThreadpoolWait ntdll.TpSetWait ; Win 7 @ stdcall SetTimeZoneInformation(ptr) @ stdcall SetTimerQueueTimer(long ptr ptr long long long) -;@ stdcall -arch?x86_64 SetUmsThreadInformation @ stdcall SetUnhandledExceptionFilter(ptr) @ stdcall SetUserGeoID(long) @ stdcall SetVDMCurrentDirectories(long long) @@ -1267,19 +849,12 @@ @ stdcall SetVolumeMountPointA(str str) @ stdcall SetVolumeMountPointW(wstr wstr) @ stdcall SetWaitableTimer(long ptr long ptr ptr long) -;@ stdcall SetWaitableTimerEx api-ms-win-core-threadpool-l1-1-0.SetWaitableTimerEx ; Win 7 @ stdcall SetupComm(long long long) @ stdcall ShowConsoleCursor(long long) @ stdcall SignalObjectAndWait(long long long long) @ stdcall SizeofResource(long long) @ stdcall Sleep(long) -;@ stdcall SleepConditionVariableCS ; Win 7 -;@ stdcall SleepConditionVariableSRW ; Win 7 @ stdcall SleepEx(long long) -;@ stdcall SortCloseHandle ; Win 7 -;@ stdcall SortGetHandle ; Win 7 -;@ stdcall StartThreadpoolIo ntdll.TpStartAsyncIoOperation ; Win 7 -;@ stdcall SubmitThreadpoolWork ntdll.TpPostWork ; Win 7 @ stdcall SuspendThread(long) @ stdcall SwitchToFiber(ptr) @ stdcall SwitchToThread() @@ -1292,52 +867,37 @@ @ stdcall Thread32First(long ptr) @ stdcall Thread32Next(long ptr) @ stdcall TlsAlloc() -;@ stub TlsAllocInternal ; missing in XP SP3 and Win 7 @ stdcall TlsFree(long) -;@ stub TlsFreeInternal ; missing in XP SP3 and Win 7 @ stdcall TlsGetValue(long) @ stdcall TlsSetValue(long ptr) @ stdcall Toolhelp32ReadProcessMemory(long ptr ptr long ptr) @ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr) @ stdcall TransmitCommChar(long long) -@ stdcall TrimVirtualBuffer(ptr) ; missing in Win 7 -;@ stdcall TryAcquireSRWLockExclusive ntdll.RtlTryAcquireSRWLockExclusive ; Win 7 -;@ stdcall TryAcquireSRWLockShared ntdll.RtlTryAcquireSRWLockShared ; Win 7 @ stdcall TryEnterCriticalSection(ptr) ntdll.RtlTryEnterCriticalSection -;@ stdcall TrySubmitThreadpoolCallback ; Win 7 @ stdcall TzSpecificLocalTimeToSystemTime(ptr ptr ptr) @ stdcall UTRegister(long str str str ptr ptr ptr) @ stdcall UTUnRegister(long) -;@ stdcall -arch=x86_64 UmsThreadYield @ stdcall UnhandledExceptionFilter(ptr) -;@ stdcall UninitializeCriticalSection(ptr) ; ??? @ stdcall UnlockFile(long long long long long) @ stdcall UnlockFileEx(long long long long ptr) @ stdcall UnmapViewOfFile(ptr) -;@ stdcall UnregisterApplicationRecoveryCallback ; Win 7 -;@ stdcall UnregisterApplicationRestart ; Win 7 @ stdcall UnregisterConsoleIME() @ stdcall UnregisterWait(long) @ stdcall UnregisterWaitEx(long long) -;@ stdcall UpdateCalendarDayOfWeek ; Win 7 -;@ stdcall UpdateProcThreadAttribute api-ms-win-core-processthreads-l1-1-0.UpdateProcThreadAttribute ; Win 7 @ stdcall UpdateResourceA(long str str long ptr long) @ stdcall UpdateResourceW(long wstr wstr long ptr long) @ stdcall VDMConsoleOperation(long long) @ stdcall VDMOperationStarted(long) -;@ stub ValidateCType ; missing in XP SP3 and Win 7 -;@ stub ValidateLocale ; missing in XP SP3 and Win 7 +@ stdcall ValidateLCType(long long ptr ptr) +@ stdcall ValidateLocale(long) @ stdcall VerLanguageNameA(long str long) @ stdcall VerLanguageNameW(long wstr long) @ stdcall -ret64 VerSetConditionMask(long long long long) ntdll.VerSetConditionMask @ stdcall VerifyConsoleIoHandle(long) -;@ stdcall VerifyScripts ; Win 7 @ stdcall VerifyVersionInfoA(long long double) @ stdcall VerifyVersionInfoW(long long double) @ stdcall VirtualAlloc(ptr long long long) @ stdcall VirtualAllocEx(long ptr long long long) -;@ stdcall VirtualAllocExNuma ; Win 7 -@ stdcall VirtualBufferExceptionHandler(long long long) ; missing in Win 7 @ stdcall VirtualFree(ptr long long) @ stdcall VirtualFreeEx(long ptr long long) @ stdcall VirtualLock(ptr long) @@ -1346,44 +906,20 @@ @ stdcall VirtualQuery(ptr ptr long) @ stdcall VirtualQueryEx(long ptr ptr long) @ stdcall VirtualUnlock(ptr long) -;@ stdcall WTSGetActiveConsoleSessionId ; Win 7 +@ stdcall WTSGetActiveConsoleSessionId() @ stdcall WaitCommEvent(long ptr ptr) @ stdcall WaitForDebugEvent(ptr long) @ stdcall WaitForMultipleObjects(long ptr long long) @ stdcall WaitForMultipleObjectsEx(long ptr long long long) @ stdcall WaitForSingleObject(long long) @ stdcall WaitForSingleObjectEx(long long long) -;@ stdcall WaitForThreadpoolIoCallbacks ntdll.TpWaitForIoCompletion ; Win 7 -;@ stdcall WaitForThreadpoolTimerCallbacks ntdll.TpWaitForTimer ; Win 7 -;@ stdcall WaitForThreadpoolWaitCallbacks ntdll.TpWaitForWait ; Win 7 -;@ stdcall WaitForThreadpoolWorkCallbacks ntdll.TpWaitForWork ; Win 7 @ stdcall WaitNamedPipeA (str long) @ stdcall WaitNamedPipeW (wstr long) -@ stdcall WakeAllConditionVariable(ptr) ntdll.RtlWakeAllConditionVariable -@ stdcall WakeConditionVariable(ptr) ntdll.RtlWakeConditionVariable -;@ stdcall WerGetFlags ; Win 7 -;@ stdcall WerRegisterFile ; Win 7 -;@ stdcall WerRegisterMemoryBlock ; Win 7 -;@ stdcall WerRegisterRuntimeExceptionModule ; Win 7 -;@ stdcall WerSetFlags ; Win 7 -;@ stdcall WerUnregisterFile ; Win 7 -;@ stdcall WerUnregisterMemoryBlock ; Win 7 -;@ stdcall WerUnregisterRuntimeExceptionModule ; Win 7 -;@ stdcall WerpCleanupMessageMapping ; Win 7 -;@ stdcall WerpInitiateRemoteRecovery ; Win 7 -;@ stdcall WerpNotifyLoadStringResource ; Win 7 -;@ stdcall WerpNotifyLoadStringResourceEx ; Win 7 -;@ stdcall WerpNotifyUseStringResource ; Win 7 -;@ stdcall WerpStringLookup ; Win 7 @ stdcall WideCharToMultiByte(long long wstr long ptr long ptr ptr) @ stdcall WinExec(str long) @ stdcall Wow64DisableWow64FsRedirection(ptr) @ stdcall Wow64EnableWow64FsRedirection(long) -;@ stdcall Wow64GetThreadContext ; Win 7 -;@ stdcall Wow64GetThreadSelectorEntry ; Win 7 @ stdcall Wow64RevertWow64FsRedirection(ptr) -;@ stdcall Wow64SetThreadContext ; Win 7 -;@ stdcall Wow64SuspendThread ; Win 7 @ stdcall WriteConsoleA(long ptr long ptr ptr) @ stdcall WriteConsoleInputA(long ptr long ptr) @ stdcall WriteConsoleInputVDMA(long long long long) @@ -1410,23 +946,15 @@ @ stdcall WriteProfileStringA(str str str) @ stdcall WriteProfileStringW(wstr wstr wstr) @ stdcall WriteTapemark(ptr long long long) -@ stdcall WTSGetActiveConsoleSessionId() ; missing in win 7 @ stdcall ZombifyActCtx(ptr) -;@ stdcall -arch=x86_64 __C_specific_handler ntdll.__C_specific_handler -;@ stdcall -arch=x86_64 __chkstk ntdll.__chkstk -;@ stdcall -arch=x86_64 __misaligned_access ntdll.__misaligned_access -;@ stub _DebugOut ; missing in XP SP3 and Win 7 -;@ stub _DebugPrintf ; missing in XP SP3 and Win 7 @ stdcall _hread(long ptr long) @ stdcall _hwrite(long ptr long) @ stdcall _lclose(long) @ stdcall _lcreat(str long) @ stdcall _llseek(long long long) -;@ stdcall -arch=x86_64 _local_unwind ntdll._local_unwind; Win 7 @ stdcall _lopen(str long) @ stdcall _lread(long ptr long) _hread @ stdcall _lwrite(long ptr long) _hwrite -;@ stub dprintf ; missing in XP SP3 and Win 7 @ stdcall lstrcat(str str) lstrcatA @ stdcall lstrcatA(str str) @ stdcall lstrcatW(wstr wstr) @@ -1445,12 +973,17 @@ @ stdcall lstrlen(str) lstrlenA @ stdcall lstrlenA(str) @ stdcall lstrlenW(wstr) -;@ stdcall -arch=x86_64 uaw_lstrcmpW ; Win 7 -;@ stdcall -arch=x86_64 uaw_lstrcmpiW ; Win 7 -;@ stdcall -arch=x86_64 uaw_lstrlenW ; Win 7 -;@ stdcall -arch=x86_64 uaw_wcschr ; Win 7 -;@ stdcall -arch=x86_64 uaw_wcscpy ; Win 7 -;@ stdcall -arch=x86_64 uaw_wcsicmp ; Win 7 -;@ stdcall -arch=x86_64 uaw_wcslen ; Win 7 -;@ stdcall -arch=x86_64 uaw_wcsrchr ; Win 7 +@ cdecl -arch=x86_64 RtlAddFunctionTable(ptr long long) ntdll.RtlAddFunctionTable +@ stdcall -arch=x86_64 RtlCompareMemory(ptr ptr ptr) +@ stdcall -arch=x86_64 RtlCopyMemory(ptr ptr ptr) +@ stdcall -arch=x86_64 RtlDeleteFunctionTable(ptr) +@ stdcall -arch=x86_64 RtlInstallFunctionTableCallback(double double long ptr ptr ptr) +@ stdcall -arch=x86_64 RtlLookupFunctionEntry(ptr ptr ptr) ntdll.RtlLookupFunctionEntry +@ stdcall -arch=x86_64 RtlPcToFileHeader(ptr ptr) ntdll.RtlPcToFileHeader +@ stdcall -arch=x86_64 RtlRaiseException(ptr) ntdll.RtlRaiseException +@ stdcall -arch=x86_64 RtlRestoreContext(ptr ptr) ntdll.RtlRestoreContext +@ stdcall -arch=x86_64 RtlUnwindEx(ptr ptr ptr ptr ptr ptr) ntdll.RtlUnwindEx +@ stdcall -arch=x86_64 RtlVirtualUnwind(ptr ptr ptr long) ntdll.RtlVirtualUnwind + +@ stdcall GetTickCount64() ; FOR WINE diff --git a/dll/win32/kernel32/mem/heap.c b/dll/win32/kernel32/mem/heap.c deleted file mode 100644 index 80aefa15cbe..00000000000 --- a/dll/win32/kernel32/mem/heap.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/mem/heap.c - * PURPOSE: Heap Memory APIs (wrappers for RtlHeap*) - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -#define NDEBUG -#include - -/* TYPES *********************************************************************/ - -extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo; - -/* FUNCTIONS ***************************************************************/ - -/* - * @implemented - */ -HANDLE -WINAPI -HeapCreate(DWORD flOptions, - DWORD dwInitialSize, - DWORD dwMaximumSize) -{ - HANDLE hRet; - ULONG Flags; - - /* Remove non-Win32 flags and tag this allocation */ - Flags = (flOptions & (HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE)) | - HEAP_CLASS_1; - - /* Check if heap is growable and ensure max size is correct */ - if (dwMaximumSize == 0) - Flags |= HEAP_GROWABLE; - else if (dwMaximumSize < BaseCachedSysInfo.PageSize && - dwInitialSize > dwMaximumSize) - { - /* Max size is non-zero but less than page size which can't be correct. - Fix it up by bumping it to the initial size whatever it is. */ - dwMaximumSize = dwInitialSize; - } - - /* Call RTL Heap */ - hRet = RtlCreateHeap(Flags, - NULL, - dwMaximumSize, - dwInitialSize, - NULL, - NULL); - - /* Set the last error if we failed, and return the pointer */ - if (!hRet) SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return hRet; -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapDestroy(HANDLE hHeap) -{ - /* Return TRUE if the heap was destroyed */ - if (!RtlDestroyHeap(hHeap)) return TRUE; - - /* Otherwise, we got the handle back, so fail */ - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; -} - -/* - * @implemented - */ -HANDLE -WINAPI -GetProcessHeap(VOID) -{ - /* Call the RTL API */ - return RtlGetProcessHeap(); -} - -/* - * @implemented - */ -DWORD -WINAPI -GetProcessHeaps(DWORD NumberOfHeaps, - PHANDLE ProcessHeaps) -{ - /* Call the RTL API */ - return RtlGetProcessHeaps(NumberOfHeaps, ProcessHeaps); -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapLock(HANDLE hHeap) -{ - /* Call the RTL API */ - return RtlLockHeap(hHeap); -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapUnlock(HANDLE hHeap) -{ - /* Call the RTL API */ - return RtlUnlockHeap(hHeap); -} - -/* - * @implemented - */ -SIZE_T -WINAPI -HeapCompact(HANDLE hHeap, DWORD dwFlags) -{ - /* Call the RTL API */ - return RtlCompactHeap(hHeap, dwFlags); -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapValidate(HANDLE hHeap, - DWORD dwFlags, - LPCVOID lpMem) -{ - /* Call the RTL API */ - return RtlValidateHeap(hHeap, dwFlags, (PVOID)lpMem); -} - -/* - * @implemented - */ -DWORD -WINAPI -HeapCreateTagsW(HANDLE hHeap, - DWORD dwFlags, - PWSTR lpTagName, - PWSTR lpTagSubName) -{ - /* Call the RTL API */ - return RtlCreateTagHeap(hHeap, - dwFlags, - lpTagName, - lpTagSubName); -} - -/* - * @implemented - */ -DWORD -WINAPI -HeapExtend(HANDLE hHeap, - DWORD dwFlags, - PVOID BaseAddress, - DWORD dwBytes) -{ - NTSTATUS Status; - - /* Call the RTL API. Gone in Vista, so commented out. */ - Status = STATUS_NOT_IMPLEMENTED; //RtlExtendHeap(hHeap, dwFlags, BaseAddress, dwBytes); - if (!NT_SUCCESS(Status)) - { - /* We failed */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Return success */ - return TRUE; -} - -/* - * @implemented - */ -PWSTR -WINAPI -HeapQueryTagW(HANDLE hHeap, - DWORD dwFlags, - WORD wTagIndex, - BOOL bResetCounters, - PVOID lpTagInfo) -{ - /* Call the RTL API */ - return RtlQueryTagHeap(hHeap, - dwFlags, - wTagIndex, - (BOOLEAN)bResetCounters, - lpTagInfo); -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapSummary(HANDLE hHeap, - DWORD dwFlags, - PVOID Summary) -{ - NTSTATUS Status; - RTL_HEAP_USAGE Usage; - - /* Fill in the length information */ - Usage.Length = sizeof(Usage); - - /* Call RTL. Gone in Vista, so commented out */ - Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage); - if (!NT_SUCCESS(Status)) - { - /* We failed */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* FIXME: Summary == Usage?! */ - RtlCopyMemory(Summary, &Usage, sizeof(Usage)); - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapUsage(HANDLE hHeap, - DWORD dwFlags, - DWORD Unknown, - DWORD Unknown2, - IN PVOID Usage) -{ - NTSTATUS Status; - - /* Call RTL. Gone in Vista, so commented out */ - Status = STATUS_NOT_IMPLEMENTED; //RtlUsageHeap(hHeap, dwFlags, &Usage); - if (!NT_SUCCESS(Status)) - { - /* We failed */ - SetLastErrorByStatus(Status); - return FALSE; - } - else if (Status == STATUS_MORE_ENTRIES) - { - /* There are still more entries to parse */ - return TRUE; - } - - /* Otherwise, we're completely done, so we return FALSE, but NO_ERROR */ - SetLastError(NO_ERROR); - return FALSE; -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapWalk(HANDLE hHeap, - LPPROCESS_HEAP_ENTRY lpEntry) -{ - NTSTATUS Status; - - Status = RtlWalkHeap(hHeap, lpEntry); - - if (!NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return FALSE; - } - - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapQueryInformation(HANDLE HeapHandle, - HEAP_INFORMATION_CLASS HeapInformationClass, - PVOID HeapInformation OPTIONAL, - SIZE_T HeapInformationLength OPTIONAL, - PSIZE_T ReturnLength OPTIONAL) -{ - NTSTATUS Status; - - Status = RtlQueryHeapInformation(HeapHandle, - HeapInformationClass, - HeapInformation, - HeapInformationLength, - ReturnLength); - - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - -/* - * @implemented - */ -BOOL -WINAPI -HeapSetInformation(HANDLE HeapHandle, - HEAP_INFORMATION_CLASS HeapInformationClass, - PVOID HeapInformation OPTIONAL, - SIZE_T HeapInformationLength OPTIONAL) -{ - NTSTATUS Status; - - Status = RtlSetHeapInformation(HeapHandle, - HeapInformationClass, - HeapInformation, - HeapInformationLength); - - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/mem/isbad.c b/dll/win32/kernel32/mem/isbad.c deleted file mode 100644 index 1b186f10530..00000000000 --- a/dll/win32/kernel32/mem/isbad.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/mem/isbad.c - * PURPOSE: Handles probing of memory addresses - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - * Thomas Weidenmueller (w3seek@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -#define NDEBUG -#include - -extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo; - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -BOOL -WINAPI -IsBadReadPtr(IN LPCVOID lp, - IN UINT_PTR ucb) -{ - ULONG PageSize; - BOOLEAN Result = FALSE; - volatile CHAR *Current; - PCHAR Last; - - /* Quick cases */ - if (!ucb) return FALSE; - if (!lp) return TRUE; - - /* Get the page size */ - PageSize = BaseCachedSysInfo.PageSize; - - /* Calculate the last page */ - Last = (PCHAR)((ULONG_PTR)lp + ucb - 1); - - /* Another quick failure case */ - if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE; - - /* Enter SEH */ - _SEH2_TRY - { - /* Probe the entire range */ - Current = (volatile CHAR*)lp; - Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); - do - { - *Current; - Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE); - } while (Current <= Last); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* We hit an exception, so return true */ - Result = TRUE; - } - _SEH2_END - - /* Return exception status */ - return Result; -} - -/* - * @implemented - */ -BOOL -NTAPI -IsBadHugeReadPtr(LPCVOID lp, - UINT_PTR ucb) -{ - /* Implementation is the same on 32-bit */ - return IsBadReadPtr(lp, ucb); -} - -/* - * @implemented - */ -BOOL -NTAPI -IsBadCodePtr(FARPROC lpfn) -{ - /* Executing has the same privileges as reading */ - return IsBadReadPtr((LPVOID)lpfn, 1); -} - -/* - * @implemented - */ -BOOL -NTAPI -IsBadWritePtr(LPVOID lp, - UINT_PTR ucb) -{ - ULONG PageSize; - BOOLEAN Result = FALSE; - volatile CHAR *Current; - PCHAR Last; - - /* Quick cases */ - if (!ucb) return FALSE; - if (!lp) return TRUE; - - /* Get the page size */ - PageSize = BaseCachedSysInfo.PageSize; - - /* Calculate the last page */ - Last = (PCHAR)((ULONG_PTR)lp + ucb - 1); - - /* Another quick failure case */ - if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE; - - /* Enter SEH */ - _SEH2_TRY - { - /* Probe the entire range */ - Current = (volatile CHAR*)lp; - Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); - do - { - *Current = *Current; - Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE); - } while (Current <= Last); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* We hit an exception, so return true */ - Result = TRUE; - } - _SEH2_END - - /* Return exception status */ - return Result; -} - -/* - * @implemented - */ -BOOL -NTAPI -IsBadHugeWritePtr(LPVOID lp, - UINT_PTR ucb) -{ - /* Implementation is the same on 32-bit */ - return IsBadWritePtr(lp, ucb); -} - -/* - * @implemented - */ -BOOL -NTAPI -IsBadStringPtrW(IN LPCWSTR lpsz, - UINT_PTR ucchMax) -{ - BOOLEAN Result = FALSE; - volatile WCHAR *Current; - PWCHAR Last; - WCHAR Char; - - /* Quick cases */ - if (!ucchMax) return FALSE; - if (!lpsz) return TRUE; - - /* Calculate the last page */ - Last = (PWCHAR)((ULONG_PTR)lpsz + (ucchMax * 2) - 2); - - /* Enter SEH */ - _SEH2_TRY - { - /* Probe the entire range */ - Current = (volatile WCHAR*)lpsz; - Last = (PWCHAR)(PAGE_ROUND_DOWN(Last)); - do - { - Char = *Current; - Current++; - } while (Char && (Current != Last + 1)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* We hit an exception, so return true */ - Result = TRUE; - } - _SEH2_END - - /* Return exception status */ - return Result; -} - -/* - * @implemented - */ -BOOL -NTAPI -IsBadStringPtrA(IN LPCSTR lpsz, - UINT_PTR ucchMax) -{ - BOOLEAN Result = FALSE; - volatile CHAR *Current; - PCHAR Last; - CHAR Char; - - /* Quick cases */ - if (!ucchMax) return FALSE; - if (!lpsz) return TRUE; - - /* Calculate the last page */ - Last = (PCHAR)((ULONG_PTR)lpsz + ucchMax - 1); - - /* Enter SEH */ - _SEH2_TRY - { - /* Probe the entire range */ - Current = (volatile CHAR*)lpsz; - Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); - do - { - Char = *Current; - Current++; - } while (Char && (Current != Last + 1)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* We hit an exception, so return true */ - Result = TRUE; - } - _SEH2_END - - /* Return exception status */ - return Result; -} - -/* EOF */ diff --git a/dll/win32/kernel32/mem/local.c b/dll/win32/kernel32/mem/local.c deleted file mode 100644 index 875ae4bce8a..00000000000 --- a/dll/win32/kernel32/mem/local.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/mem/local.c - * PURPOSE: Local Memory APIs (sits on top of Heap*) - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -#define NDEBUG -#include - -/* TYPES *********************************************************************/ - -extern SYSTEM_BASIC_INFORMATION BaseCachedSysInfo; - -/* FUNCTIONS ***************************************************************/ - -/* - * @implemented - */ -HLOCAL -NTAPI -LocalAlloc(UINT uFlags, - SIZE_T dwBytes) -{ - ULONG Flags = 0; - PVOID Ptr = NULL; - HANDLE hMemory; - PBASE_HEAP_HANDLE_ENTRY HandleEntry; - BASE_TRACE_ALLOC(dwBytes, uFlags); - ASSERT(hProcessHeap); - - /* Make sure the flags are valid */ - if (uFlags & ~LMEM_VALID_FLAGS) - { - /* They aren't, fail */ - BASE_TRACE_FAILURE(); - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Convert ZEROINIT */ - if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; - - /* Check if we're not movable, which means pointer-based heap */ - if (!(uFlags & LMEM_MOVEABLE)) - { - /* Allocate heap for it */ - Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); - BASE_TRACE_ALLOC2(Ptr); - return Ptr; - } - - /* This is heap based, so lock it in first */ - RtlLockHeap(hProcessHeap); - - /* - * Disable locking, enable custom flags, and write the - * movable flag (deprecated) - */ - Flags |= HEAP_NO_SERIALIZE | - HEAP_SETTABLE_USER_VALUE | - BASE_HEAP_FLAG_MOVABLE; - - /* Allocate the handle */ - HandleEntry = BaseHeapAllocEntry(); - if (!HandleEntry) - { - /* Fail */ - hMemory = NULL; - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - BASE_TRACE_FAILURE(); - goto Quickie; - } - - /* Get the object and make sure we have size */ - hMemory = &HandleEntry->Object; - if (dwBytes) - { - /* Allocate the actual memory for it */ - Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); - BASE_TRACE_PTR(HandleEntry, Ptr); - if (!Ptr) - { - /* We failed, manually set the allocate flag and free the handle */ - HandleEntry->Flags = RTL_HANDLE_VALID; - BaseHeapFreeEntry(HandleEntry); - - /* For the cleanup case */ - HandleEntry = NULL; - } - else - { - /* All worked well, save our heap entry */ - RtlSetUserValueHeap(hProcessHeap, HEAP_NO_SERIALIZE, Ptr, hMemory); - } - } - -Quickie: - /* Cleanup! First unlock the heap */ - RtlUnlockHeap(hProcessHeap); - - /* Check if a handle was allocated */ - if (HandleEntry) - { - /* Set the pointer and allocated flag */ - HandleEntry->Object = Ptr; - HandleEntry->Flags = RTL_HANDLE_VALID; - if (!Ptr) - { - /* We don't have a valid pointer, but so reuse this handle */ - HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; - } - - /* Check if the handle is discardable */ - if (uFlags & GMEM_DISCARDABLE) - { - /* Save it in the handle entry */ - HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; - } - - /* Check if the handle is moveable */ - if (uFlags & GMEM_MOVEABLE) - { - /* Save it in the handle entry */ - HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_MOVABLE; - } - - /* Set the pointer */ - Ptr = hMemory; - } - - /* Return the pointer */ - return Ptr; -} - -/* - * @implemented - */ -SIZE_T -NTAPI -LocalCompact(UINT dwMinFree) -{ - /* Call the RTL Heap Manager */ - return RtlCompactHeap(hProcessHeap, 0); -} - -/* - * @implemented - */ -UINT -NTAPI -LocalFlags(HLOCAL hMem) -{ - PBASE_HEAP_HANDLE_ENTRY HandleEntry; - HANDLE Handle = NULL; - ULONG Flags = 0; - UINT uFlags = LMEM_INVALID_HANDLE; - - /* Start by locking the heap */ - RtlLockHeap(hProcessHeap); - - /* Check if this is a simple RTL Heap Managed block */ - if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) - { - /* Then we'll query RTL Heap */ - RtlGetUserInfoHeap(hProcessHeap, Flags, hMem, &Handle, &Flags); - BASE_TRACE_PTR(Handle, hMem); - - /* - * Check if RTL Heap didn't find a handle associated with us or - * said that this heap isn't movable, which means something we're - * really not a handle-based heap. - */ - if (!(Handle) || !(Flags & BASE_HEAP_FLAG_MOVABLE)) - { - /* Then set the flags to 0 */ - uFlags = 0; - } - else - { - /* Otherwise we're handle-based, so get the internal handle */ - hMem = Handle; - } - } - - /* Check if the handle is actually an entry in our table */ - if ((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY) - { - /* Then get the entry */ - HandleEntry = BaseHeapGetEntry(hMem); - BASE_TRACE_HANDLE(HandleEntry, hMem); - - /* Make sure it's a valid handle */ - if (BaseHeapValidateEntry(HandleEntry)) - { - /* Get the lock count first */ - uFlags = HandleEntry->LockCount & LMEM_LOCKCOUNT; - - /* Now check if it's discardable */ - if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSABLE) - { - /* Set the Win32 Flag */ - uFlags |= LMEM_DISCARDABLE; - } - - /* Now check if it's discarded */ - if (HandleEntry->Flags & BASE_HEAP_ENTRY_FLAG_REUSE) - /* Set the Win32 Flag */ - uFlags |= LMEM_DISCARDED; - } - } - - /* Check if by now, we still haven't gotten any useful flags */ - if (uFlags == LMEM_INVALID_HANDLE) SetLastError(ERROR_INVALID_HANDLE); - - /* All done! Unlock heap and return Win32 Flags */ - RtlUnlockHeap(hProcessHeap); - return uFlags; -} - -/* - * @implemented - */ -HLOCAL -NTAPI -LocalFree(HLOCAL hMem) -{ - /* This is identical to a Global Free */ - return GlobalFree(hMem); -} - -/* - * @implemented - */ -HLOCAL -NTAPI -LocalHandle(LPCVOID pMem) -{ - /* This is identical to a Global Handle */ - return GlobalHandle(pMem); -} - -/* - * @implemented - */ -LPVOID -NTAPI -LocalLock(HLOCAL hMem) -{ - /* This is the same as a GlobalLock, assuming these never change */ - C_ASSERT(LMEM_LOCKCOUNT == GMEM_LOCKCOUNT); - return GlobalLock(hMem); -} - -HLOCAL -NTAPI -LocalReAlloc(HLOCAL hMem, - SIZE_T dwBytes, - UINT uFlags) -{ - PBASE_HEAP_HANDLE_ENTRY HandleEntry; - LPVOID Ptr; - ULONG Flags = 0; - - /* Convert ZEROINIT */ - if (uFlags & LMEM_ZEROINIT) Flags |= HEAP_ZERO_MEMORY; - - /* If this wasn't a movable heap, then we MUST re-alloc in place */ - if (!(uFlags & LMEM_MOVEABLE)) Flags |= HEAP_REALLOC_IN_PLACE_ONLY; - - /* Lock the heap and disable built-in locking in the RTL Heap funcitons */ - RtlLockHeap(hProcessHeap); - Flags |= HEAP_NO_SERIALIZE; - - /* Check if this is a simple handle-based block */ - if (((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) - { - /* Get the entry */ - HandleEntry = BaseHeapGetEntry(hMem); - BASE_TRACE_HANDLE(HandleEntry, hMem); - - /* Make sure the handle is valid */ - if (!BaseHeapValidateEntry(HandleEntry)) - { - /* Fail */ - BASE_TRACE_FAILURE(); - SetLastError(ERROR_INVALID_HANDLE); - hMem = NULL; - } - else if (uFlags & LMEM_MODIFY) - { - /* User is changing flags... check if the memory was discardable */ - if (uFlags & LMEM_DISCARDABLE) - { - /* Then set the flag */ - HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSABLE; - } - else - { - /* Otherwise, remove the flag */ - HandleEntry->Flags &= BASE_HEAP_ENTRY_FLAG_REUSABLE; - } - } - else - { - /* Otherwise, get the object and check if we have no size */ - Ptr = HandleEntry->Object; - if (!dwBytes) - { - /* Clear the handle and check for a pointer */ - hMem = NULL; - if (Ptr) - { - /* Make sure the handle isn't locked */ - if ((uFlags & LMEM_MOVEABLE) && !(HandleEntry->LockCount)) - { - /* Free the current heap */ - RtlFreeHeap(hProcessHeap, Flags, Ptr); - - /* Free the handle */ - HandleEntry->Object = NULL; - HandleEntry->Flags |= BASE_HEAP_ENTRY_FLAG_REUSE; - - /* Get the object pointer */ - hMem = &HandleEntry->Object; - } - } - else - { - /* Otherwise just return the object pointer */ - hMem = &HandleEntry->Object; - } - } - else - { - /* Otherwise, we're allocating, so set the new flags needed */ - Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVABLE; - if (!Ptr) - { - /* We don't have a base, so allocate one */ - Ptr = RtlAllocateHeap(hProcessHeap, Flags, dwBytes); - BASE_TRACE_ALLOC2(Ptr); - if (Ptr) - { - /* Allocation succeeded, so save our entry */ - RtlSetUserValueHeap(hProcessHeap, - HEAP_NO_SERIALIZE, - Ptr, - hMem); - } - } - else - { - /* - * If it's not movable or currently locked, we MUST allocate - * in-place! - */ - if (!(uFlags & LMEM_MOVEABLE) && (HandleEntry->LockCount)) - { - /* Set the flag */ - Flags |= HEAP_REALLOC_IN_PLACE_ONLY; - } - else - { - /* Otherwise clear the flag if we set it previously */ - Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY; - } - - /* And do the re-allocation */ - Ptr = RtlReAllocateHeap(hProcessHeap, Flags, Ptr, dwBytes); - } - - /* Make sure we have a pointer by now */ - if (Ptr) - { - /* Write it in the handle entry and mark it in use */ - HandleEntry->Object = Ptr; - HandleEntry->Flags &= ~BASE_HEAP_ENTRY_FLAG_REUSE; - } - else - { - /* Otherwise we failed */ - hMem = NULL; - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - } - } - } - else if (!(uFlags & LMEM_MODIFY)) - { - /* Otherwise, this is a simple RTL Managed Heap, so just call it */ - hMem = RtlReAllocateHeap(hProcessHeap, - Flags | HEAP_NO_SERIALIZE, - hMem, - dwBytes); - if (!hMem) - { - /* Fail */ - BASE_TRACE_FAILURE(); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - } - - /* All done, unlock the heap and return the pointer */ - RtlUnlockHeap(hProcessHeap); - return hMem; -} - -/* - * @implemented - */ -SIZE_T -WINAPI -LocalShrink(HLOCAL hMem, - UINT cbNewSize) -{ - /* Call RTL */ - return RtlCompactHeap(hProcessHeap, 0); -} - -/* - * @implemented - */ -SIZE_T -NTAPI -LocalSize(HLOCAL hMem) -{ - /* This is the same as a Global Size */ - return GlobalSize(hMem); -} - -/* - * @implemented - */ -BOOL -NTAPI -LocalUnlock(HLOCAL hMem) -{ - PBASE_HEAP_HANDLE_ENTRY HandleEntry; - BOOL RetVal = TRUE; - - /* Check if this was a simple allocated heap entry */ - if (!((ULONG_PTR)hMem & BASE_HEAP_IS_HANDLE_ENTRY)) - { - /* Fail, because LocalUnlock is not supported on LMEM_FIXED allocations */ - SetLastError(ERROR_NOT_LOCKED); - return FALSE; - } - - /* Otherwise, lock the heap */ - RtlLockHeap(hProcessHeap); - - /* Get the handle entry */ - HandleEntry = BaseHeapGetEntry(hMem); - BASE_TRACE_HANDLE(HandleEntry, hMem); - - _SEH2_TRY - { - /* Make sure it's valid */ - if (!BaseHeapValidateEntry(HandleEntry)) - { - /* It's not, fail */ - BASE_TRACE_FAILURE(); - SetLastError(ERROR_INVALID_HANDLE); - RetVal = FALSE; - } - else - { - /* Otherwise, decrement lock count, unless we're already at 0*/ - if (!HandleEntry->LockCount--) - { - /* In which case we simply lock it back and fail */ - HandleEntry->LockCount++; - SetLastError(ERROR_NOT_LOCKED); - RetVal = FALSE; - } - else if (!HandleEntry->LockCount) - { - /* Nothing to unlock */ - SetLastError(NO_ERROR); - RetVal = FALSE; - } - } - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastError(ERROR_INVALID_PARAMETER); - RetVal = FALSE; - } - _SEH2_END - - /* All done. Unlock the heap and return the pointer */ - RtlUnlockHeap(hProcessHeap); - return RetVal; -} - -/* EOF */ diff --git a/dll/win32/kernel32/mem/procmem.c b/dll/win32/kernel32/mem/procmem.c deleted file mode 100644 index 354804e75c6..00000000000 --- a/dll/win32/kernel32/mem/procmem.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/mem/procmem.c - * PURPOSE: Handles virtual memory APIs - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -BOOL -NTAPI -ReadProcessMemory(IN HANDLE hProcess, - IN LPCVOID lpBaseAddress, - IN LPVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T* lpNumberOfBytesRead) -{ - NTSTATUS Status; - - /* Do the read */ - Status = NtReadVirtualMemory(hProcess, - (PVOID)lpBaseAddress, - lpBuffer, - nSize, - lpNumberOfBytesRead); - if (!NT_SUCCESS(Status)) - { - /* We failed */ - SetLastErrorByStatus (Status); - return FALSE; - } - - /* Return success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL -NTAPI -WriteProcessMemory(IN HANDLE hProcess, - IN LPVOID lpBaseAddress, - IN LPCVOID lpBuffer, - IN SIZE_T nSize, - OUT SIZE_T *lpNumberOfBytesWritten) -{ - NTSTATUS Status; - ULONG OldValue; - SIZE_T RegionSize; - PVOID Base; - BOOLEAN UnProtect; - - /* Set parameters for protect call */ - RegionSize = nSize; - Base = lpBaseAddress; - - /* Check the current status */ - Status = NtProtectVirtualMemory(hProcess, - &Base, - &RegionSize, - PAGE_EXECUTE_READWRITE, - &OldValue); - if (NT_SUCCESS(Status)) - { - /* Check if we are unprotecting */ - UnProtect = OldValue & (PAGE_READWRITE | - PAGE_WRITECOPY | - PAGE_EXECUTE_READWRITE | - PAGE_EXECUTE_WRITECOPY) ? FALSE : TRUE; - if (!UnProtect) - { - /* Set the new protection */ - Status = NtProtectVirtualMemory(hProcess, - &Base, - &RegionSize, - OldValue, - &OldValue); - - /* Write the memory */ - Status = NtWriteVirtualMemory(hProcess, - lpBaseAddress, - (LPVOID)lpBuffer, - nSize, - lpNumberOfBytesWritten); - if (!NT_SUCCESS(Status)) - { - /* We failed */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Flush the ITLB */ - NtFlushInstructionCache(hProcess, lpBaseAddress, nSize); - return TRUE; - } - else - { - /* Check if we were read only */ - if ((OldValue & PAGE_NOACCESS) || (OldValue & PAGE_READONLY)) - { - /* Restore protection and fail */ - NtProtectVirtualMemory(hProcess, - &Base, - &RegionSize, - OldValue, - &OldValue); - SetLastErrorByStatus(STATUS_ACCESS_VIOLATION); - return FALSE; - } - - /* Otherwise, do the write */ - Status = NtWriteVirtualMemory(hProcess, - lpBaseAddress, - (LPVOID)lpBuffer, - nSize, - lpNumberOfBytesWritten); - - /* And restore the protection */ - NtProtectVirtualMemory(hProcess, - &Base, - &RegionSize, - OldValue, - &OldValue); - if (!NT_SUCCESS(Status)) - { - /* We failed */ - SetLastErrorByStatus(STATUS_ACCESS_VIOLATION); - return FALSE; - } - - /* Flush the ITLB */ - NtFlushInstructionCache(hProcess, lpBaseAddress, nSize); - return TRUE; - } - } - else - { - /* We failed */ - SetLastErrorByStatus(Status); - return FALSE; - } -} - -/* EOF */ diff --git a/dll/win32/kernel32/mem/resnotify.c b/dll/win32/kernel32/mem/resnotify.c deleted file mode 100644 index 2251702f519..00000000000 --- a/dll/win32/kernel32/mem/resnotify.c +++ /dev/null @@ -1,103 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: lib/kernel32/mem/resnotify.c - * PURPOSE: Memory Resource Notification - * PROGRAMMER: Thomas Weidenmueller - */ - -/* INCLUDES ******************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -HANDLE -WINAPI -CreateMemoryResourceNotification( - MEMORY_RESOURCE_NOTIFICATION_TYPE NotificationType - ) -{ - UNICODE_STRING EventName; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hEvent; - NTSTATUS Status; - - switch(NotificationType) - { - case LowMemoryResourceNotification: - RtlInitUnicodeString(&EventName, L"\\KernelObjects\\LowMemoryCondition"); - break; - - case HighMemoryResourceNotification: - RtlInitUnicodeString(&EventName, L"\\KernelObjects\\HighMemoryCondition"); - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - InitializeObjectAttributes(&ObjectAttributes, - &EventName, - 0, - hBaseDir, - NULL); - - Status = NtOpenEvent(&hEvent, - EVENT_QUERY_STATE | SYNCHRONIZE, - &ObjectAttributes); - if(!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return NULL; - } - - return hEvent; -} - - -/* - * @implemented - */ -BOOL -WINAPI -QueryMemoryResourceNotification( - HANDLE ResourceNotificationHandle, - PBOOL ResourceState - ) -{ - EVENT_BASIC_INFORMATION ebi; - NTSTATUS Status; - - if(ResourceState != NULL) - { - Status = NtQueryEvent(ResourceNotificationHandle, - EventBasicInformation, - &ebi, - sizeof(ebi), - NULL); - if(NT_SUCCESS(Status)) - { - *ResourceState = ebi.EventState; - return TRUE; - } - - SetLastErrorByStatus(Status); - } - else /* ResourceState == NULL */ - { - SetLastError(ERROR_INVALID_PARAMETER); - } - - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/misc/ldr.c b/dll/win32/kernel32/misc/ldr.c index b2874cf3b73..2f5e0ac9356 100644 --- a/dll/win32/kernel32/misc/ldr.c +++ b/dll/win32/kernel32/misc/ldr.c @@ -863,7 +863,7 @@ BasepGetModuleHandleExW(BOOLEAN NoLock, DWORD dwPublicFlags, LPCWSTR lpwModuleNa if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) { /* Add reference to this DLL */ - Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0, + Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_ADDREF_DLL_PIN : 0, hModule); } diff --git a/dll/win32/kernel32/misc/utils.c b/dll/win32/kernel32/misc/utils.c index a011ff5e6e3..ff0276e42f8 100644 --- a/dll/win32/kernel32/misc/utils.c +++ b/dll/win32/kernel32/misc/utils.c @@ -424,7 +424,7 @@ BasepMapFile(IN LPCWSTR lpApplicationName, OUT PHANDLE hSection, IN PUNICODE_STRING ApplicationName) { - CURDIR RelativeName; + RTL_RELATIVE_NAME_U RelativeName; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE hFile = NULL; @@ -433,7 +433,7 @@ BasepMapFile(IN LPCWSTR lpApplicationName, DPRINT("BasepMapFile\n"); /* Zero out the Relative Directory */ - RelativeName.Handle = NULL; + RelativeName.ContainingDirectory = NULL; /* Find the application name */ if (!RtlDosPathNameToNtPathName_U(lpApplicationName, @@ -445,19 +445,19 @@ BasepMapFile(IN LPCWSTR lpApplicationName, } DPRINT("ApplicationName %wZ\n", ApplicationName); - DPRINT("RelativeName %wZ\n", &RelativeName.DosPath); + DPRINT("RelativeName %wZ\n", &RelativeName.RelativeName); /* Did we get a relative name? */ - if (RelativeName.DosPath.Length) + if (RelativeName.RelativeName.Length) { - ApplicationName = &RelativeName.DosPath; + ApplicationName = &RelativeName.RelativeName; } /* Initialize the Object Attributes */ InitializeObjectAttributes(&ObjectAttributes, ApplicationName, OBJ_CASE_INSENSITIVE, - RelativeName.Handle, + RelativeName.ContainingDirectory, NULL); /* Try to open the executable */ diff --git a/dll/win32/kernel32/process/cmdline.c b/dll/win32/kernel32/process/cmdline.c deleted file mode 100644 index 2c2b2421966..00000000000 --- a/dll/win32/kernel32/process/cmdline.c +++ /dev/null @@ -1,97 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/proc/proc.c - * PURPOSE: Process functions - * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - * UPDATE HISTORY: - * Created 01/11/98 - */ - -/* INCLUDES ****************************************************************/ - -#include - -#define NDEBUG -#include - - -/* GLOBALS ******************************************************************/ - -static UNICODE_STRING CommandLineStringW; -static ANSI_STRING CommandLineStringA; - -static BOOL bCommandLineInitialized = FALSE; - - -/* FUNCTIONS ****************************************************************/ - -VOID -WINAPI -InitCommandLines(VOID) -{ - PRTL_USER_PROCESS_PARAMETERS Params; - - /* get command line */ - Params = NtCurrentPeb()->ProcessParameters; - RtlNormalizeProcessParams (Params); - - /* initialize command line buffers */ - CommandLineStringW.Length = Params->CommandLine.Length; - CommandLineStringW.MaximumLength = CommandLineStringW.Length + sizeof(WCHAR); - CommandLineStringW.Buffer = RtlAllocateHeap(GetProcessHeap(), - HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, - CommandLineStringW.MaximumLength); - if (CommandLineStringW.Buffer == NULL) - { - return; - } - - RtlInitAnsiString(&CommandLineStringA, NULL); - - /* Copy command line */ - RtlCopyUnicodeString(&CommandLineStringW, - &(Params->CommandLine)); - CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0; - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - RtlUnicodeStringToAnsiString(&CommandLineStringA, - &CommandLineStringW, - TRUE); - else - RtlUnicodeStringToOemString(&CommandLineStringA, - &CommandLineStringW, - TRUE); - - CommandLineStringA.Buffer[CommandLineStringA.Length] = 0; - - bCommandLineInitialized = TRUE; -} - - -/* - * @implemented - */ -LPSTR -WINAPI -GetCommandLineA(VOID) -{ - DPRINT("CommandLine \'%s\'\n", CommandLineStringA.Buffer); - return CommandLineStringA.Buffer; -} - - -/* - * @implemented - */ -LPWSTR -WINAPI -GetCommandLineW(VOID) -{ - DPRINT("CommandLine \'%S\'\n", CommandLineStringW.Buffer); - return CommandLineStringW.Buffer; -} - -/* EOF */ diff --git a/dll/win32/kernel32/process/proc.c b/dll/win32/kernel32/process/proc.c deleted file mode 100644 index 41889ec8b4a..00000000000 --- a/dll/win32/kernel32/process/proc.c +++ /dev/null @@ -1,1137 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/proc/proc.c - * PURPOSE: Process functions - * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - * UPDATE HISTORY: - * Created 01/11/98 - */ - -/* INCLUDES ****************************************************************/ - -#include - -#define NDEBUG -#include - - -typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT); - -/* GLOBALS *******************************************************************/ - -WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle; - -LPSTARTUPINFOA lpLocalStartupInfo = NULL; - -VOID WINAPI -RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle); - -/* FUNCTIONS ****************************************************************/ - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessAffinityMask(HANDLE hProcess, - PDWORD_PTR lpProcessAffinityMask, - PDWORD_PTR lpSystemAffinityMask) -{ - PROCESS_BASIC_INFORMATION ProcessInfo; - SYSTEM_BASIC_INFORMATION SystemInfo; - NTSTATUS Status; - - Status = NtQuerySystemInformation(SystemBasicInformation, - &SystemInfo, - sizeof(SystemInfo), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - Status = NtQueryInformationProcess(hProcess, - ProcessBasicInformation, - (PVOID)&ProcessInfo, - sizeof(PROCESS_BASIC_INFORMATION), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask; - *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessorsAffinityMask; - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -SetProcessAffinityMask(HANDLE hProcess, - DWORD_PTR dwProcessAffinityMask) -{ - NTSTATUS Status; - - Status = NtSetInformationProcess(hProcess, - ProcessAffinityMask, - (PVOID)&dwProcessAffinityMask, - sizeof(DWORD)); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessShutdownParameters(LPDWORD lpdwLevel, - LPDWORD lpdwFlags) -{ - CSR_API_MESSAGE CsrRequest; - ULONG Request; - NTSTATUS Status; - - Request = GET_SHUTDOWN_PARAMETERS; - Status = CsrClientCallServer(&CsrRequest, - NULL, - MAKE_CSR_API(Request, CSR_NATIVE), - sizeof(CSR_API_MESSAGE)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level; - *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags; - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -SetProcessShutdownParameters(DWORD dwLevel, - DWORD dwFlags) -{ - CSR_API_MESSAGE CsrRequest; - ULONG Request; - NTSTATUS Status; - - CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel; - CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags; - - Request = SET_SHUTDOWN_PARAMETERS; - Status = CsrClientCallServer(&CsrRequest, - NULL, - MAKE_CSR_API(Request, CSR_NATIVE), - sizeof(CSR_API_MESSAGE)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessWorkingSetSize(HANDLE hProcess, - PSIZE_T lpMinimumWorkingSetSize, - PSIZE_T lpMaximumWorkingSetSize) -{ - QUOTA_LIMITS QuotaLimits; - NTSTATUS Status; - - Status = NtQueryInformationProcess(hProcess, - ProcessQuotaLimits, - &QuotaLimits, - sizeof(QUOTA_LIMITS), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - *lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize; - *lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize; - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -SetProcessWorkingSetSize(HANDLE hProcess, - SIZE_T dwMinimumWorkingSetSize, - SIZE_T dwMaximumWorkingSetSize) -{ - QUOTA_LIMITS QuotaLimits; - NTSTATUS Status; - - QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize; - QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize; - - Status = NtSetInformationProcess(hProcess, - ProcessQuotaLimits, - &QuotaLimits, - sizeof(QUOTA_LIMITS)); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessTimes(HANDLE hProcess, - LPFILETIME lpCreationTime, - LPFILETIME lpExitTime, - LPFILETIME lpKernelTime, - LPFILETIME lpUserTime) -{ - KERNEL_USER_TIMES Kut; - NTSTATUS Status; - - Status = NtQueryInformationProcess(hProcess, - ProcessTimes, - &Kut, - sizeof(Kut), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart; - lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart; - - lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart; - lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart; - - lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart; - lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart; - - lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart; - lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart; - - return TRUE; -} - - -/* - * @implemented - */ -HANDLE -WINAPI -GetCurrentProcess(VOID) -{ - return (HANDLE)NtCurrentProcess(); -} - - -/* - * @implemented - */ -HANDLE -WINAPI -GetCurrentThread(VOID) -{ - return (HANDLE)NtCurrentThread(); -} - - -/* - * @implemented - */ -DWORD -WINAPI -GetCurrentProcessId(VOID) -{ - return HandleToUlong(GetTeb()->ClientId.UniqueProcess); -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetExitCodeProcess(HANDLE hProcess, - LPDWORD lpExitCode) -{ - PROCESS_BASIC_INFORMATION ProcessBasic; - NTSTATUS Status; - - Status = NtQueryInformationProcess(hProcess, - ProcessBasicInformation, - &ProcessBasic, - sizeof(PROCESS_BASIC_INFORMATION), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - *lpExitCode = (DWORD)ProcessBasic.ExitStatus; - - return TRUE; -} - - -/* - * @implemented - */ -DWORD -WINAPI -GetProcessId(HANDLE Process) -{ - PROCESS_BASIC_INFORMATION ProcessBasic; - NTSTATUS Status; - - Status = NtQueryInformationProcess(Process, - ProcessBasicInformation, - &ProcessBasic, - sizeof(PROCESS_BASIC_INFORMATION), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return 0; - } - - return (DWORD)ProcessBasic.UniqueProcessId; -} - - -/* - * @implemented - */ -HANDLE -WINAPI -OpenProcess(DWORD dwDesiredAccess, - BOOL bInheritHandle, - DWORD dwProcessId) -{ - NTSTATUS errCode; - HANDLE ProcessHandle; - OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID ClientId; - - ClientId.UniqueProcess = UlongToHandle(dwProcessId); - ClientId.UniqueThread = 0; - - InitializeObjectAttributes(&ObjectAttributes, - NULL, - (bInheritHandle ? OBJ_INHERIT : 0), - NULL, - NULL); - - errCode = NtOpenProcess(&ProcessHandle, - dwDesiredAccess, - &ObjectAttributes, - &ClientId); - if (!NT_SUCCESS(errCode)) - { - SetLastErrorByStatus(errCode); - return NULL; - } - - return ProcessHandle; -} - - -/* - * @implemented - */ -UINT -WINAPI -WinExec(LPCSTR lpCmdLine, - UINT uCmdShow) -{ - STARTUPINFOA StartupInfo; - PROCESS_INFORMATION ProcessInformation; - DWORD dosErr; - - RtlZeroMemory(&StartupInfo, sizeof(StartupInfo)); - StartupInfo.cb = sizeof(STARTUPINFOA); - StartupInfo.wShowWindow = (WORD)uCmdShow; - StartupInfo.dwFlags = 0; - - if (!CreateProcessA(NULL, - (PVOID)lpCmdLine, - NULL, - NULL, - FALSE, - 0, - NULL, - NULL, - &StartupInfo, - &ProcessInformation)) - { - dosErr = GetLastError(); - return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT; - } - - if (NULL != lpfnGlobalRegisterWaitForInputIdle) - { - lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, - 10000); - } - - NtClose(ProcessInformation.hProcess); - NtClose(ProcessInformation.hThread); - - return 33; /* Something bigger than 31 means success. */ -} - - -/* - * @implemented - */ -VOID -WINAPI -RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle) -{ - lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle; - return; -} - -/* - * @implemented - */ -VOID -WINAPI -GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo) -{ - PRTL_USER_PROCESS_PARAMETERS Params; - - if (lpStartupInfo == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return; - } - - Params = NtCurrentPeb()->ProcessParameters; - - lpStartupInfo->cb = sizeof(STARTUPINFOW); - lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer; - lpStartupInfo->lpTitle = Params->WindowTitle.Buffer; - lpStartupInfo->dwX = Params->StartingX; - lpStartupInfo->dwY = Params->StartingY; - lpStartupInfo->dwXSize = Params->CountX; - lpStartupInfo->dwYSize = Params->CountY; - lpStartupInfo->dwXCountChars = Params->CountCharsX; - lpStartupInfo->dwYCountChars = Params->CountCharsY; - lpStartupInfo->dwFillAttribute = Params->FillAttribute; - lpStartupInfo->dwFlags = Params->WindowFlags; - lpStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags; - lpStartupInfo->cbReserved2 = Params->RuntimeData.Length; - lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer; - - lpStartupInfo->hStdInput = Params->StandardInput; - lpStartupInfo->hStdOutput = Params->StandardOutput; - lpStartupInfo->hStdError = Params->StandardError; -} - - -/* - * @implemented - */ -VOID -WINAPI -GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) -{ - PRTL_USER_PROCESS_PARAMETERS Params; - ANSI_STRING AnsiString; - - if (lpStartupInfo == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return; - } - - Params = NtCurrentPeb ()->ProcessParameters; - - RtlAcquirePebLock (); - - /* FIXME - not thread-safe */ - if (lpLocalStartupInfo == NULL) - { - /* create new local startup info (ansi) */ - lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(STARTUPINFOA)); - if (lpLocalStartupInfo == NULL) - { - RtlReleasePebLock(); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return; - } - - lpLocalStartupInfo->cb = sizeof(STARTUPINFOA); - - /* copy window title string */ - RtlUnicodeStringToAnsiString(&AnsiString, - &Params->WindowTitle, - TRUE); - lpLocalStartupInfo->lpTitle = AnsiString.Buffer; - - /* copy desktop info string */ - RtlUnicodeStringToAnsiString(&AnsiString, - &Params->DesktopInfo, - TRUE); - lpLocalStartupInfo->lpDesktop = AnsiString.Buffer; - - /* copy shell info string */ - RtlUnicodeStringToAnsiString(&AnsiString, - &Params->ShellInfo, - TRUE); - lpLocalStartupInfo->lpReserved = AnsiString.Buffer; - - lpLocalStartupInfo->dwX = Params->StartingX; - lpLocalStartupInfo->dwY = Params->StartingY; - lpLocalStartupInfo->dwXSize = Params->CountX; - lpLocalStartupInfo->dwYSize = Params->CountY; - lpLocalStartupInfo->dwXCountChars = Params->CountCharsX; - lpLocalStartupInfo->dwYCountChars = Params->CountCharsY; - lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute; - lpLocalStartupInfo->dwFlags = Params->WindowFlags; - lpLocalStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags; - lpLocalStartupInfo->cbReserved2 = Params->RuntimeData.Length; - lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer; - - lpLocalStartupInfo->hStdInput = Params->StandardInput; - lpLocalStartupInfo->hStdOutput = Params->StandardOutput; - lpLocalStartupInfo->hStdError = Params->StandardError; - } - - RtlReleasePebLock(); - - /* copy local startup info data to external startup info */ - memcpy(lpStartupInfo, - lpLocalStartupInfo, - sizeof(STARTUPINFOA)); -} - - -/* - * @implemented - */ -BOOL -WINAPI -FlushInstructionCache(HANDLE hProcess, - LPCVOID lpBaseAddress, - SIZE_T dwSize) -{ - NTSTATUS Status; - - Status = NtFlushInstructionCache(hProcess, - (PVOID)lpBaseAddress, - dwSize); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -VOID -WINAPI -ExitProcess(UINT uExitCode) -{ - CSR_API_MESSAGE CsrRequest; - ULONG Request; - NTSTATUS Status; - - /* kill sibling threads ... we want to be alone at this point */ - NtTerminateProcess(NULL, 0); - - /* unload all dll's */ - LdrShutdownProcess(); - - /* notify csrss of process termination */ - Request = TERMINATE_PROCESS; - Status = CsrClientCallServer(&CsrRequest, - NULL, - MAKE_CSR_API(Request, CSR_NATIVE), - sizeof(CSR_API_MESSAGE)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) - { - DPRINT("Failed to tell csrss about terminating process\n"); - } - - NtTerminateProcess(NtCurrentProcess (), - uExitCode); - - /* should never get here */ - ASSERT(0); - while(1); -} - - -/* - * @implemented - */ -BOOL -WINAPI -TerminateProcess(HANDLE hProcess, - UINT uExitCode) -{ - NTSTATUS Status; - - if (hProcess == NULL) - { - return FALSE; - } - - Status = NtTerminateProcess(hProcess, uExitCode); - if (NT_SUCCESS(Status)) - { - return TRUE; - } - - SetLastErrorByStatus(Status); - return FALSE; -} - - -/* - * @unimplemented - */ -VOID -WINAPI -FatalAppExitA(UINT uAction, - LPCSTR lpMessageText) -{ - UNICODE_STRING MessageTextU; - ANSI_STRING MessageText; - - RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText); - - RtlAnsiStringToUnicodeString(&MessageTextU, - &MessageText, - TRUE); - - FatalAppExitW(uAction, MessageTextU.Buffer); - - RtlFreeUnicodeString(&MessageTextU); -} - - -/* - * @unimplemented - */ -VOID -WINAPI -FatalAppExitW(UINT uAction, - LPCWSTR lpMessageText) -{ - static const WCHAR szUser32[] = L"user32.dll\0"; - - HMODULE hModule = GetModuleHandleW(szUser32); - MessageBoxW_Proc pMessageBoxW = NULL; - - DPRINT1("AppExit\n"); - - if (hModule) - pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule, "MessageBoxW"); - - if (pMessageBoxW) - pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK); - else - DPRINT1("%s\n", lpMessageText); - - ExitProcess(0); -} - - -/* - * @implemented - */ -VOID -WINAPI -FatalExit(int ExitCode) -{ - ExitProcess(ExitCode); -} - - -/* - * @implemented - */ -DWORD -WINAPI -GetPriorityClass(HANDLE hProcess) -{ - NTSTATUS Status; - PROCESS_PRIORITY_CLASS PriorityClass; - - Status = NtQueryInformationProcess(hProcess, - ProcessPriorityClass, - &PriorityClass, - sizeof(PROCESS_PRIORITY_CLASS), - NULL); - if(NT_SUCCESS(Status)) - { - switch(PriorityClass.PriorityClass) - { - case PROCESS_PRIORITY_CLASS_IDLE: - return IDLE_PRIORITY_CLASS; - - case PROCESS_PRIORITY_CLASS_BELOW_NORMAL: - return BELOW_NORMAL_PRIORITY_CLASS; - - case PROCESS_PRIORITY_CLASS_NORMAL: - return NORMAL_PRIORITY_CLASS; - - case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL: - return ABOVE_NORMAL_PRIORITY_CLASS; - - case PROCESS_PRIORITY_CLASS_HIGH: - return HIGH_PRIORITY_CLASS; - - case PROCESS_PRIORITY_CLASS_REALTIME: - return REALTIME_PRIORITY_CLASS; - - default: - return NORMAL_PRIORITY_CLASS; - } - } - - SetLastErrorByStatus(Status); - return FALSE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -SetPriorityClass(HANDLE hProcess, - DWORD dwPriorityClass) -{ - NTSTATUS Status; - PROCESS_PRIORITY_CLASS PriorityClass; - - switch (dwPriorityClass) - { - case IDLE_PRIORITY_CLASS: - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; - break; - - case BELOW_NORMAL_PRIORITY_CLASS: - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; - break; - - case NORMAL_PRIORITY_CLASS: - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; - break; - - case ABOVE_NORMAL_PRIORITY_CLASS: - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; - break; - - case HIGH_PRIORITY_CLASS: - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; - break; - - case REALTIME_PRIORITY_CLASS: - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME; - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - PriorityClass.Foreground = FALSE; - - Status = NtSetInformationProcess(hProcess, - ProcessPriorityClass, - &PriorityClass, - sizeof(PROCESS_PRIORITY_CLASS)); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -DWORD -WINAPI -GetProcessVersion(DWORD ProcessId) -{ - DWORD Version = 0; - PIMAGE_NT_HEADERS NtHeader = NULL; - IMAGE_NT_HEADERS NtHeaders; - IMAGE_DOS_HEADER DosHeader; - PROCESS_BASIC_INFORMATION ProcessBasicInfo; - PVOID BaseAddress = NULL; - HANDLE ProcessHandle = NULL; - NTSTATUS Status; - SIZE_T Count; - PEB Peb; - - _SEH2_TRY - { - if (0 == ProcessId || GetCurrentProcessId() == ProcessId) - { - /* Caller's */ - BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress; - NtHeader = RtlImageNtHeader(BaseAddress); - - Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) | - (NtHeader->OptionalHeader.MinorOperatingSystemVersion); - } - else - { - /* Other process */ - ProcessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, - FALSE, - ProcessId); - - if (!ProcessHandle) return 0; - - Status = NtQueryInformationProcess(ProcessHandle, - ProcessBasicInformation, - &ProcessBasicInfo, - sizeof(ProcessBasicInfo), - NULL); - - if (!NT_SUCCESS(Status)) goto Error; - - Status = NtReadVirtualMemory(ProcessHandle, - ProcessBasicInfo.PebBaseAddress, - &Peb, - sizeof(Peb), - &Count); - - if (!NT_SUCCESS(Status) || Count != sizeof(Peb)) goto Error; - - memset(&DosHeader, 0, sizeof(DosHeader)); - Status = NtReadVirtualMemory(ProcessHandle, - Peb.ImageBaseAddress, - &DosHeader, - sizeof(DosHeader), - &Count); - - if (!NT_SUCCESS(Status) || Count != sizeof(DosHeader)) goto Error; - if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) goto Error; - - memset(&NtHeaders, 0, sizeof(NtHeaders)); - Status = NtReadVirtualMemory(ProcessHandle, - (char *)Peb.ImageBaseAddress + DosHeader.e_lfanew, - &NtHeaders, - sizeof(NtHeaders), - &Count); - - if (!NT_SUCCESS(Status) || Count != sizeof(NtHeaders)) goto Error; - if (NtHeaders.Signature != IMAGE_NT_SIGNATURE) goto Error; - - Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion, - NtHeaders.OptionalHeader.MajorSubsystemVersion); - -Error: - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - } - } - } - _SEH2_FINALLY - { - if (ProcessHandle) CloseHandle(ProcessHandle); - } - _SEH2_END; - - return Version; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessIoCounters(HANDLE hProcess, - PIO_COUNTERS lpIoCounters) -{ - NTSTATUS Status; - - Status = NtQueryInformationProcess(hProcess, - ProcessIoCounters, - lpIoCounters, - sizeof(IO_COUNTERS), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessPriorityBoost(HANDLE hProcess, - PBOOL pDisablePriorityBoost) -{ - NTSTATUS Status; - ULONG PriorityBoost; - - Status = NtQueryInformationProcess(hProcess, - ProcessPriorityBoost, - &PriorityBoost, - sizeof(ULONG), - NULL); - if (NT_SUCCESS(Status)) - { - *pDisablePriorityBoost = PriorityBoost; - return TRUE; - } - - SetLastErrorByStatus(Status); - return FALSE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -SetProcessPriorityBoost(HANDLE hProcess, - BOOL bDisablePriorityBoost) -{ - NTSTATUS Status; - ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */ - - Status = NtSetInformationProcess(hProcess, - ProcessPriorityBoost, - &PriorityBoost, - sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetProcessHandleCount(HANDLE hProcess, - PDWORD pdwHandleCount) -{ - ULONG phc; - NTSTATUS Status; - - Status = NtQueryInformationProcess(hProcess, - ProcessHandleCount, - &phc, - sizeof(ULONG), - NULL); - if(NT_SUCCESS(Status)) - { - *pdwHandleCount = phc; - return TRUE; - } - - SetLastErrorByStatus(Status); - return FALSE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -IsWow64Process(HANDLE hProcess, - PBOOL Wow64Process) -{ - ULONG_PTR pbi; - NTSTATUS Status; - - Status = NtQueryInformationProcess(hProcess, - ProcessWow64Information, - &pbi, - sizeof(pbi), - NULL); - if (!NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return FALSE; - } - - *Wow64Process = (pbi != 0); - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -QueryFullProcessImageNameW(HANDLE hProcess, - DWORD dwFlags, - LPWSTR lpExeName, - PDWORD pdwSize) -{ - BYTE Buffer[sizeof(UNICODE_STRING) + MAX_PATH * sizeof(WCHAR)]; - UNICODE_STRING *DynamicBuffer = NULL; - UNICODE_STRING *Result = NULL; - NTSTATUS Status; - DWORD Needed; - - Status = NtQueryInformationProcess(hProcess, - ProcessImageFileName, - Buffer, - sizeof(Buffer) - sizeof(WCHAR), - &Needed); - if (Status == STATUS_INFO_LENGTH_MISMATCH) - { - DynamicBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Needed + sizeof(WCHAR)); - if (!DynamicBuffer) - { - SetLastErrorByStatus(STATUS_NO_MEMORY); - return FALSE; - } - - Status = NtQueryInformationProcess(hProcess, - ProcessImageFileName, - (LPBYTE)DynamicBuffer, - Needed, - &Needed); - Result = DynamicBuffer; - } - else Result = (PUNICODE_STRING)Buffer; - - if (!NT_SUCCESS(Status)) goto Cleanup; - - if (Result->Length / sizeof(WCHAR) + 1 > *pdwSize) - { - Status = STATUS_BUFFER_TOO_SMALL; - goto Cleanup; - } - - *pdwSize = Result->Length / sizeof(WCHAR); - memcpy(lpExeName, Result->Buffer, Result->Length); - lpExeName[*pdwSize] = 0; - -Cleanup: - RtlFreeHeap(RtlGetProcessHeap(), 0, DynamicBuffer); - - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - } - - return !Status; -} - - -/* - * @implemented - */ -BOOL -WINAPI -QueryFullProcessImageNameA(HANDLE hProcess, - DWORD dwFlags, - LPSTR lpExeName, - PDWORD pdwSize) -{ - DWORD pdwSizeW = *pdwSize; - BOOL Result; - LPWSTR lpExeNameW; - - lpExeNameW = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - *pdwSize * sizeof(WCHAR)); - if (!lpExeNameW) - { - SetLastErrorByStatus(STATUS_NO_MEMORY); - return FALSE; - } - - Result = QueryFullProcessImageNameW(hProcess, dwFlags, lpExeNameW, &pdwSizeW); - - if (Result) - Result = (0 != WideCharToMultiByte(CP_ACP, 0, - lpExeNameW, - -1, - lpExeName, - *pdwSize, - NULL, NULL)); - - if (Result) - *pdwSize = strlen(lpExeName); - - RtlFreeHeap(RtlGetProcessHeap(), 0, lpExeNameW); - return Result; -} - -/* EOF */ diff --git a/dll/win32/kernel32/process/session.c b/dll/win32/kernel32/process/session.c deleted file mode 100644 index 7e9dcd148d7..00000000000 --- a/dll/win32/kernel32/process/session.c +++ /dev/null @@ -1,115 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/proc/session.c - * PURPOSE: Win32 session (TS) functions - * PROGRAMMER: Emanuele Aliberti - * UPDATE HISTORY: - * 2001-12-07 created - */ -#include -#define NDEBUG -#include -//DEBUG_CHANNEL(kernel32session); not actually used - -DWORD ActiveConsoleSessionId = 0; - - -/* - * @unimplemented - */ -DWORD -WINAPI -DosPathToSessionPathW(DWORD SessionID, - LPWSTR InPath, - LPWSTR *OutPath) -{ - UNIMPLEMENTED; - return 0; -} - -/* - * From: ActiveVB.DE - * - * Declare Function DosPathToSessionPath _ - * Lib "kernel32.dll" _ - * Alias "DosPathToSessionPathA" ( _ - * ByVal SessionId As Long, _ - * ByVal pInPath As String, _ - * ByVal ppOutPath As String ) _ - * As Long - * - * @unimplemented - */ -DWORD -WINAPI -DosPathToSessionPathA(DWORD SessionId, - LPSTR InPath, - LPSTR *OutPath) -{ - //DosPathToSessionPathW (SessionId,InPathW,OutPathW); - UNIMPLEMENTED; - return 0; -} - -/* - * @implemented - */ -BOOL -WINAPI -ProcessIdToSessionId(IN DWORD dwProcessId, - OUT DWORD *pSessionId) -{ - PROCESS_SESSION_INFORMATION SessionInformation; - OBJECT_ATTRIBUTES ObjectAttributes; - CLIENT_ID ClientId; - HANDLE ProcessHandle; - NTSTATUS Status; - - if (IsBadWritePtr(pSessionId, sizeof(DWORD))) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ClientId.UniqueProcess = UlongToHandle(dwProcessId); - ClientId.UniqueThread = 0; - - InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); - - Status = NtOpenProcess(&ProcessHandle, - PROCESS_QUERY_INFORMATION, - &ObjectAttributes, - &ClientId); - if (NT_SUCCESS(Status)) - { - Status = NtQueryInformationProcess(ProcessHandle, - ProcessSessionInformation, - &SessionInformation, - sizeof(SessionInformation), - NULL); - NtClose(ProcessHandle); - - if (NT_SUCCESS(Status)) - { - *pSessionId = SessionInformation.SessionId; - return TRUE; - } - } - - SetLastErrorByStatus(Status); - return FALSE; -} - -/* - * @implemented - */ -DWORD -WINAPI -WTSGetActiveConsoleSessionId(VOID) -{ - return ActiveConsoleSessionId; -} - -/* EOF */ diff --git a/dll/win32/kernel32/synch/condvar.c b/dll/win32/kernel32/synch/condvar.c deleted file mode 100644 index 6eebbccff90..00000000000 --- a/dll/win32/kernel32/synch/condvar.c +++ /dev/null @@ -1,95 +0,0 @@ -/* COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Condition Variable functions - * PROGRAMMER: Thomas Weidenmueller - */ - -#include - -#define NDEBUG -#include - -/* FIXME: Move these RTL declarations to the NDK */ -NTSTATUS -NTAPI -RtlSleepConditionVariableCS(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, - IN OUT PRTL_CRITICAL_SECTION CriticalSection, - IN PLARGE_INTEGER TimeOut OPTIONAL); - -NTSTATUS -NTAPI -RtlSleepConditionVariableSRW(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, - IN OUT PRTL_SRWLOCK SRWLock, - IN PLARGE_INTEGER TimeOut OPTIONAL, - IN ULONG Flags); - -/* PUBLIC FUNCTIONS ***********************************************************/ - -/* - * @implemented - */ -BOOL -WINAPI -SleepConditionVariableCS(IN OUT PCONDITION_VARIABLE ConditionVariable, - IN OUT PCRITICAL_SECTION CriticalSection, - IN DWORD dwMilliseconds) -{ - NTSTATUS Status = 0; - LARGE_INTEGER TimeOut; - PLARGE_INTEGER TimeOutPtr = NULL; - - if (dwMilliseconds != INFINITE) - { - TimeOut.QuadPart = UInt32x32To64(-10000, dwMilliseconds); - TimeOutPtr = &TimeOut; - } - -#if 0 - Status = RtlSleepConditionVariableCS((PRTL_CONDITION_VARIABLE)ConditionVariable, - (PRTL_CRITICAL_SECTION)CriticalSection, - TimeOutPtr); -#endif - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -SleepConditionVariableSRW(IN OUT PCONDITION_VARIABLE ConditionVariable, - IN OUT PSRWLOCK SRWLock, - IN DWORD dwMilliseconds, - IN ULONG Flags) -{ - NTSTATUS Status = 0; - LARGE_INTEGER TimeOut; - PLARGE_INTEGER TimeOutPtr = NULL; - - if (dwMilliseconds != INFINITE) - { - TimeOut.QuadPart = UInt32x32To64(-10000, dwMilliseconds); - TimeOutPtr = &TimeOut; - } - -#if 0 - Status = RtlSleepConditionVariableSRW((PRTL_CONDITION_VARIABLE)ConditionVariable, - (PRTL_SRWLOCK)SRWLock, - TimeOutPtr, - Flags); -#endif - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - return TRUE; -} diff --git a/dll/win32/kernel32/synch/critical.c b/dll/win32/kernel32/synch/critical.c deleted file mode 100644 index ac5280a60bd..00000000000 --- a/dll/win32/kernel32/synch/critical.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/synch/critical.c - * PURPOSE: Wrappers for the RTL Critical Section Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -VOID -WINAPI -InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection) -{ - NTSTATUS Status; - - /* Initialize the critical section and raise an exception if we failed */ - Status = RtlInitializeCriticalSection( - (PRTL_CRITICAL_SECTION)lpCriticalSection); - if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status); -} - -/* - * @implemented - */ -BOOL -WINAPI -InitializeCriticalSectionAndSpinCount(OUT LPCRITICAL_SECTION lpCriticalSection, - IN DWORD dwSpinCount) -{ - NTSTATUS Status; - - /* Initialize the critical section */ - Status = RtlInitializeCriticalSectionAndSpinCount( - (PRTL_CRITICAL_SECTION)lpCriticalSection, - dwSpinCount); - if (!NT_SUCCESS(Status)) - { - /* Set failure code */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Success */ - return TRUE; -} - -/* - * @implemented - */ -BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, - IN DWORD dwSpinCount, - IN DWORD flags ) -{ - NTSTATUS Status; - - /* FIXME: Flags ignored */ - - /* Initialize the critical section */ - Status = RtlInitializeCriticalSectionAndSpinCount( - (PRTL_CRITICAL_SECTION)lpCriticalSection, - dwSpinCount); - if (!NT_SUCCESS(Status)) - { - /* Set failure code */ - SetLastErrorByStatus(Status); - return FALSE; - } - - /* Success */ - return TRUE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/synch/event.c b/dll/win32/kernel32/synch/event.c deleted file mode 100644 index 3f1d7951350..00000000000 --- a/dll/win32/kernel32/synch/event.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/synch/event.c - * PURPOSE: Wrappers for the NT Event Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -HANDLE -WINAPI -CreateEventExA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, - IN LPCSTR lpName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - LPCWSTR UnicodeName = NULL; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Otherwise, save the buffer */ - UnicodeName = (LPCWSTR)UnicodeCache->Buffer; - } - - /* Call the Unicode API */ - return CreateEventExW(lpEventAttributes, - UnicodeName, - dwFlags, - dwDesiredAccess); - -} - -HANDLE -WINAPI -CreateEventExW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, - IN LPCWSTR lpName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - OBJECT_ATTRIBUTES LocalAttributes; - POBJECT_ATTRIBUTES ObjectAttributes; - HANDLE Handle; - UNICODE_STRING ObjectName; - BOOLEAN InitialState; - EVENT_TYPE EventType; - - /* Now check if we got a name */ - if (lpName) RtlInitUnicodeString(&ObjectName, lpName); - - /* Check for invalid flags */ - if (dwFlags & ~(CREATE_EVENT_INITIAL_SET | CREATE_EVENT_MANUAL_RESET)) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Set initial state and event type */ - InitialState = (dwFlags & CREATE_EVENT_INITIAL_SET) ? TRUE : FALSE; - EventType = (dwFlags & CREATE_EVENT_MANUAL_RESET) ? NotificationEvent : SynchronizationEvent; - - /* Now convert the object attributes */ - ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, - lpEventAttributes, - lpName ? &ObjectName : NULL); - - /* Create the event */ - Status = NtCreateEvent(&Handle, - (ACCESS_MASK)dwDesiredAccess, - ObjectAttributes, - EventType, - InitialState); - if (NT_SUCCESS(Status)) - { - /* Check if the object already existed */ - if (Status == STATUS_OBJECT_NAME_EXISTS) - { - /* Set distinguished Win32 error code */ - SetLastError(ERROR_ALREADY_EXISTS); - } - else - { - /* Otherwise, set success */ - SetLastError(ERROR_SUCCESS); - } - - /* Return the handle */ - return Handle; - } - else - { - /* Convert the NT Status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - -} - -HANDLE -WINAPI -CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, - IN BOOL bManualReset, - IN BOOL bInitialState, - IN LPCSTR lpName OPTIONAL) -{ - DWORD dwFlags = 0; - - /* Set new flags */ - if (bManualReset) dwFlags |= CREATE_EVENT_MANUAL_RESET; - if (bInitialState) dwFlags |= CREATE_EVENT_INITIAL_SET; - - /* Call the newer API */ - return CreateEventExA(lpEventAttributes, - lpName, - dwFlags, - EVENT_ALL_ACCESS); -} - -HANDLE -WINAPI -CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, - IN BOOL bManualReset, - IN BOOL bInitialState, - IN LPCWSTR lpName OPTIONAL) -{ - DWORD dwFlags = 0; - - /* Set new flags */ - if (bManualReset) dwFlags |= CREATE_EVENT_MANUAL_RESET; - if (bInitialState) dwFlags |= CREATE_EVENT_INITIAL_SET; - - /* Call the newer API */ - return CreateEventExW(lpEventAttributes, - lpName, - dwFlags, - EVENT_ALL_ACCESS); -} - -HANDLE -WINAPI -OpenEventA(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCSTR lpName) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - } - else - { - /* We need a name */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Call the Unicode API */ - return OpenEventW(dwDesiredAccess, - bInheritHandle, - (LPCWSTR)UnicodeCache->Buffer); -} - -HANDLE -WINAPI -OpenEventW(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCWSTR lpName) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ObjectName; - NTSTATUS Status; - HANDLE Handle; - - /* Make sure we got a name */ - if (!lpName) - { - /* Fail without one */ - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return NULL; - } - - /* Initialize the object name and attributes */ - RtlInitUnicodeString(&ObjectName, lpName); - InitializeObjectAttributes(&ObjectAttributes, - &ObjectName, - bInheritHandle ? OBJ_INHERIT : 0, - hBaseDir, - NULL); - - /* Open the event */ - Status = NtOpenEvent(&Handle, dwDesiredAccess, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - /* Convert the status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Return the handle */ - return Handle; -} - -/* - * @implemented - */ -BOOL -WINAPI -PulseEvent(IN HANDLE hEvent) -{ - NTSTATUS Status; - - /* Pulse the event */ - Status = NtPulseEvent(hEvent, NULL); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* - * @implemented - */ -BOOL -WINAPI -ResetEvent(IN HANDLE hEvent) -{ - NTSTATUS Status; - - /* Clear the event */ - Status = NtResetEvent(hEvent, NULL); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* - * @implemented - */ -BOOL -WINAPI -SetEvent(IN HANDLE hEvent) -{ - NTSTATUS Status; - - /* Set the event */ - Status = NtSetEvent(hEvent, NULL); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/synch/mutex.c b/dll/win32/kernel32/synch/mutex.c deleted file mode 100644 index 69dca56555c..00000000000 --- a/dll/win32/kernel32/synch/mutex.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/synch/mutex.c - * PURPOSE: Wrappers for the NT Mutant Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -HANDLE -WINAPI -CreateMutexExA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, - IN LPCSTR lpName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - LPCWSTR UnicodeName = NULL; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Otherwise, save the buffer */ - UnicodeName = (LPCWSTR)UnicodeCache->Buffer; - } - - /* Call the Unicode API */ - return CreateMutexExW(lpMutexAttributes, - UnicodeName, - dwFlags, - dwDesiredAccess); -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateMutexExW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, - IN LPCWSTR lpName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - OBJECT_ATTRIBUTES LocalAttributes; - POBJECT_ATTRIBUTES ObjectAttributes; - HANDLE Handle; - UNICODE_STRING ObjectName; - BOOLEAN InitialOwner; - - /* Now check if we got a name */ - if (lpName) RtlInitUnicodeString(&ObjectName, lpName); - - if (dwFlags & ~(CREATE_MUTEX_INITIAL_OWNER)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - InitialOwner = (dwFlags & CREATE_MUTEX_INITIAL_OWNER) != 0; - - /* Now convert the object attributes */ - ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, - lpMutexAttributes, - lpName ? &ObjectName : NULL); - - /* Create the mutant */ - Status = NtCreateMutant(&Handle, - (ACCESS_MASK)dwDesiredAccess, - ObjectAttributes, - InitialOwner); - if (NT_SUCCESS(Status)) - { - /* Check if the object already existed */ - if (Status == STATUS_OBJECT_NAME_EXISTS) - { - /* Set distinguished Win32 error code */ - SetLastError(ERROR_ALREADY_EXISTS); - } - else - { - /* Otherwise, set success */ - SetLastError(ERROR_SUCCESS); - } - - /* Return the handle */ - return Handle; - } - else - { - /* Convert the NT Status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, - IN BOOL bInitialOwner, - IN LPCSTR lpName OPTIONAL) -{ - DWORD dwFlags = 0; - - if (bInitialOwner) - dwFlags |= CREATE_MUTEX_INITIAL_OWNER; - - return CreateMutexExA(lpMutexAttributes, - lpName, - dwFlags, - MUTANT_ALL_ACCESS); -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, - IN BOOL bInitialOwner, - IN LPCWSTR lpName OPTIONAL) -{ - DWORD dwFlags = 0; - - if (bInitialOwner) - dwFlags |= CREATE_MUTEX_INITIAL_OWNER; - - return CreateMutexExW(lpMutexAttributes, - lpName, - dwFlags, - MUTANT_ALL_ACCESS); -} - -/* - * @implemented - */ -HANDLE -WINAPI -OpenMutexA(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCSTR lpName) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - } - else - { - /* We need a name */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Call the Unicode API */ - return OpenMutexW(dwDesiredAccess, - bInheritHandle, - (LPCWSTR)UnicodeCache->Buffer); -} - -/* - * @implemented - */ -HANDLE -WINAPI -OpenMutexW(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCWSTR lpName) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ObjectName; - NTSTATUS Status; - HANDLE Handle; - - /* Make sure we got a name */ - if (!lpName) - { - /* Fail without one */ - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return NULL; - } - - /* Initialize the object name and attributes */ - RtlInitUnicodeString(&ObjectName, lpName); - InitializeObjectAttributes(&ObjectAttributes, - &ObjectName, - bInheritHandle ? OBJ_INHERIT : 0, - hBaseDir, - NULL); - - /* Open the mutant */ - Status = NtOpenMutant(&Handle, dwDesiredAccess, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - /* Convert the status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Return the handle */ - return Handle; -} - -/* - * @implemented - */ -BOOL -WINAPI -ReleaseMutex(IN HANDLE hMutex) -{ - NTSTATUS Status; - - /* Release the mutant */ - Status = NtReleaseMutant(hMutex, NULL); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - - -/* EOF */ diff --git a/dll/win32/kernel32/synch/sem.c b/dll/win32/kernel32/synch/sem.c deleted file mode 100644 index 6b859311f4f..00000000000 --- a/dll/win32/kernel32/synch/sem.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/synch/sem.c - * PURPOSE: Wrappers for the NT Semaphore Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -/* - * @implemented - */ -HANDLE -WINAPI -CreateSemaphoreExA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, - IN LONG lInitialCount, - IN LONG lMaximumCount, - IN LPCSTR lpName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - LPCWSTR UnicodeName = NULL; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Otherwise, save the buffer */ - UnicodeName = (LPCWSTR)UnicodeCache->Buffer; - } - - /* Call the Unicode API */ - return CreateSemaphoreExW(lpSemaphoreAttributes, - lInitialCount, - lMaximumCount, - UnicodeName, - dwFlags, - dwDesiredAccess); -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateSemaphoreExW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, - IN LONG lInitialCount, - IN LONG lMaximumCount, - IN LPCWSTR lpName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - OBJECT_ATTRIBUTES LocalAttributes; - POBJECT_ATTRIBUTES ObjectAttributes; - HANDLE Handle; - UNICODE_STRING ObjectName; - - /* Now check if we got a name */ - if (lpName) RtlInitUnicodeString(&ObjectName, lpName); - - if (dwFlags != 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Now convert the object attributes */ - ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, - lpSemaphoreAttributes, - lpName ? &ObjectName : NULL); - - /* Create the semaphore */ - Status = NtCreateSemaphore(&Handle, - (ACCESS_MASK)dwDesiredAccess, - ObjectAttributes, - lInitialCount, - lMaximumCount); - if (NT_SUCCESS(Status)) - { - /* Check if the object already existed */ - if (Status == STATUS_OBJECT_NAME_EXISTS) - { - /* Set distinguished Win32 error code */ - SetLastError(ERROR_ALREADY_EXISTS); - } - else - { - /* Otherwise, set success */ - SetLastError(ERROR_SUCCESS); - } - - /* Return the handle */ - return Handle; - } - else - { - /* Convert the NT Status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - -} - - -/* - * @implemented - */ -HANDLE -WINAPI -CreateSemaphoreA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, - IN LONG lInitialCount, - IN LONG lMaximumCount, - IN LPCSTR lpName OPTIONAL) -{ - return CreateSemaphoreExA(lpSemaphoreAttributes, - lInitialCount, - lMaximumCount, - lpName, - 0, - SEMAPHORE_ALL_ACCESS); -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateSemaphoreW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, - IN LONG lInitialCount, - IN LONG lMaximumCount, - IN LPCWSTR lpName OPTIONAL) -{ - return CreateSemaphoreExW(lpSemaphoreAttributes, - lInitialCount, - lMaximumCount, - lpName, - 0, - SEMAPHORE_ALL_ACCESS); -} - -/* - * @implemented - */ -HANDLE -WINAPI -OpenSemaphoreA(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCSTR lpName) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - - /* Check for a name */ - if (lpName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - } - else - { - /* We need a name */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Call the Unicode API */ - return OpenSemaphoreW(dwDesiredAccess, - bInheritHandle, - (LPCWSTR)UnicodeCache->Buffer); -} - -/* - * @implemented - */ -HANDLE -WINAPI -OpenSemaphoreW(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCWSTR lpName) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ObjectName; - NTSTATUS Status; - HANDLE Handle; - - /* Make sure we got a name */ - if (!lpName) - { - /* Fail without one */ - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return NULL; - } - - /* Initialize the object name and attributes */ - RtlInitUnicodeString(&ObjectName, lpName); - InitializeObjectAttributes(&ObjectAttributes, - &ObjectName, - bInheritHandle ? OBJ_INHERIT : 0, - hBaseDir, - NULL); - - /* Open the semaphore */ - Status = NtOpenSemaphore(&Handle, dwDesiredAccess, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - /* Convert the status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Return the handle */ - return Handle; -} - -/* - * @implemented - */ -BOOL -WINAPI -ReleaseSemaphore(IN HANDLE hSemaphore, - IN LONG lReleaseCount, - IN LPLONG lpPreviousCount) -{ - NTSTATUS Status; - - /* Release the semaphore */ - Status = NtReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/synch/timer.c b/dll/win32/kernel32/synch/timer.c deleted file mode 100644 index fd21a1be57f..00000000000 --- a/dll/win32/kernel32/synch/timer.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/synch/timer.c - * PURPOSE: Wrappers for the NT Timer Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -/* - * @implemented - */ -HANDLE -WINAPI -CreateWaitableTimerExA(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, - IN LPCSTR lpTimerName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - LPCWSTR UnicodeName = NULL; - - /* Check for a name */ - if (lpTimerName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpTimerName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Otherwise, save the buffer */ - UnicodeName = (LPCWSTR)UnicodeCache->Buffer; - } - - /* Call the Unicode API */ - return CreateWaitableTimerExW(lpTimerAttributes, - UnicodeName, - dwFlags, - dwDesiredAccess); -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateWaitableTimerExW(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, - IN LPCWSTR lpTimerName OPTIONAL, - IN DWORD dwFlags, - IN DWORD dwDesiredAccess) -{ - NTSTATUS Status; - OBJECT_ATTRIBUTES LocalAttributes; - POBJECT_ATTRIBUTES ObjectAttributes; - HANDLE Handle; - UNICODE_STRING ObjectName; - TIMER_TYPE TimerType; - - /* Now check if we got a name */ - if (lpTimerName) RtlInitUnicodeString(&ObjectName, lpTimerName); - - if (dwFlags & ~(CREATE_WAITABLE_TIMER_MANUAL_RESET)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - TimerType = (dwFlags & CREATE_WAITABLE_TIMER_MANUAL_RESET) ? NotificationTimer : SynchronizationTimer; - - /* Now convert the object attributes */ - ObjectAttributes = BasepConvertObjectAttributes(&LocalAttributes, - lpTimerAttributes, - lpTimerName ? &ObjectName : NULL); - - /* Create the timer */ - Status = NtCreateTimer(&Handle, - (ACCESS_MASK)dwDesiredAccess, - ObjectAttributes, - TimerType); - if (NT_SUCCESS(Status)) - { - /* Check if the object already existed */ - if (Status == STATUS_OBJECT_NAME_EXISTS) - { - /* Set distinguished Win32 error code */ - SetLastError(ERROR_ALREADY_EXISTS); - } - else - { - /* Otherwise, set success */ - SetLastError(ERROR_SUCCESS); - } - - /* Return the handle */ - return Handle; - } - else - { - /* Convert the NT Status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateWaitableTimerW(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, - IN BOOL bManualReset, - IN LPCWSTR lpTimerName OPTIONAL) -{ - DWORD dwFlags = 0; - - if (bManualReset) - dwFlags |= CREATE_WAITABLE_TIMER_MANUAL_RESET; - - return CreateWaitableTimerExW(lpTimerAttributes, - lpTimerName, - dwFlags, - TIMER_ALL_ACCESS); -} - -/* - * @implemented - */ -HANDLE -WINAPI -CreateWaitableTimerA(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, - IN BOOL bManualReset, - IN LPCSTR lpTimerName OPTIONAL) -{ - DWORD dwFlags = 0; - - if (bManualReset) - dwFlags |= CREATE_WAITABLE_TIMER_MANUAL_RESET; - - return CreateWaitableTimerExA(lpTimerAttributes, - lpTimerName, - dwFlags, - TIMER_ALL_ACCESS); -} - -/* - * @implemented - */ -HANDLE -WINAPI -OpenWaitableTimerW(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCWSTR lpTimerName) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ObjectName; - NTSTATUS Status; - HANDLE Handle; - - /* Make sure we got a name */ - if (!lpTimerName) - { - /* Fail without one */ - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return NULL; - } - - /* Initialize the object name and attributes */ - RtlInitUnicodeString(&ObjectName, lpTimerName); - InitializeObjectAttributes(&ObjectAttributes, - &ObjectName, - bInheritHandle ? OBJ_INHERIT : 0, - hBaseDir, - NULL); - - /* Open the timer */ - Status = NtOpenTimer(&Handle, dwDesiredAccess, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - /* Convert the status and fail */ - SetLastErrorByStatus(Status); - return NULL; - } - - /* Return the handle */ - return Handle; -} - -/* - * @implemented - */ -HANDLE -WINAPI -OpenWaitableTimerA(IN DWORD dwDesiredAccess, - IN BOOL bInheritHandle, - IN LPCSTR lpTimerName) -{ - NTSTATUS Status; - ANSI_STRING AnsiName; - PUNICODE_STRING UnicodeCache; - - /* Check for a name */ - if (lpTimerName) - { - /* Use TEB Cache */ - UnicodeCache = &NtCurrentTeb()->StaticUnicodeString; - - /* Convert to unicode */ - RtlInitAnsiString(&AnsiName, lpTimerName); - Status = RtlAnsiStringToUnicodeString(UnicodeCache, &AnsiName, FALSE); - if (!NT_SUCCESS(Status)) - { - /* Conversion failed */ - SetLastErrorByStatus(Status); - return NULL; - } - } - else - { - /* We need a name */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Call the Unicode API */ - return OpenWaitableTimerW(dwDesiredAccess, - bInheritHandle, - (LPCWSTR)UnicodeCache->Buffer); -} - -/* - * @implemented - */ -BOOL -WINAPI -SetWaitableTimer(IN HANDLE hTimer, - IN const LARGE_INTEGER *pDueTime, - IN LONG lPeriod, - IN PTIMERAPCROUTINE pfnCompletionRoutine OPTIONAL, - IN OPTIONAL LPVOID lpArgToCompletionRoutine, - IN BOOL fResume) -{ - NTSTATUS Status; - - /* Set the timer */ - Status = NtSetTimer(hTimer, - (PLARGE_INTEGER)pDueTime, - (PTIMER_APC_ROUTINE)pfnCompletionRoutine, - lpArgToCompletionRoutine, - (BOOLEAN)fResume, - lPeriod, - NULL); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* - * @implemented - */ -BOOL -WINAPI -CancelWaitableTimer(IN HANDLE hTimer) -{ - NTSTATUS Status; - - /* Cancel the timer */ - Status = NtCancelTimer(hTimer, NULL); - if (NT_SUCCESS(Status)) return TRUE; - - /* If we got here, then we failed */ - SetLastErrorByStatus(Status); - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/synch/wait.c b/dll/win32/kernel32/synch/wait.c deleted file mode 100644 index a471b83ce51..00000000000 --- a/dll/win32/kernel32/synch/wait.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * PROJECT: ReactOS Win32 Base API - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/kernel32/synch/wait.c - * PURPOSE: Wrappers for the NT Wait Implementation - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) - */ - -/* INCLUDES *****************************************************************/ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -DWORD -WINAPI -WaitForSingleObject(IN HANDLE hHandle, - IN DWORD dwMilliseconds) -{ - /* Call the extended API */ - return WaitForSingleObjectEx(hHandle, dwMilliseconds, FALSE); -} - -/* - * @implemented - */ -DWORD -WINAPI -WaitForSingleObjectEx(IN HANDLE hHandle, - IN DWORD dwMilliseconds, - IN BOOL bAlertable) -{ - PLARGE_INTEGER TimePtr; - LARGE_INTEGER Time; - NTSTATUS Status; - - /* Get real handle */ - hHandle = TranslateStdHandle(hHandle); - - /* Check for console handle */ - if ((IsConsoleHandle(hHandle)) && (VerifyConsoleIoHandle(hHandle))) - { - /* Get the real wait handle */ - hHandle = GetConsoleInputWaitHandle(); - } - - /* Check if this is an infinite wait */ - if (dwMilliseconds == INFINITE) - { - /* Under NT, this means no timer argument */ - TimePtr = NULL; - } - else - { - /* Otherwise, convert the time to NT Format */ - Time.QuadPart = UInt32x32To64(-10000, dwMilliseconds); - TimePtr = &Time; - } - - /* Start wait loop */ - do - { - /* Do the wait */ - Status = NtWaitForSingleObject(hHandle, (BOOLEAN)bAlertable, TimePtr); - if (!NT_SUCCESS(Status)) - { - /* The wait failed */ - SetLastErrorByStatus (Status); - return WAIT_FAILED; - } - } while ((Status == STATUS_ALERTED) && (bAlertable)); - - /* Return wait status */ - return Status; -} - -/* - * @implemented - */ -DWORD -WINAPI -WaitForMultipleObjects(IN DWORD nCount, - IN CONST HANDLE *lpHandles, - IN BOOL bWaitAll, - IN DWORD dwMilliseconds) -{ - /* Call the extended API */ - return WaitForMultipleObjectsEx(nCount, - lpHandles, - bWaitAll, - dwMilliseconds, - FALSE); -} - -/* - * @implemented - */ -DWORD -WINAPI -WaitForMultipleObjectsEx(IN DWORD nCount, - IN CONST HANDLE *lpHandles, - IN BOOL bWaitAll, - IN DWORD dwMilliseconds, - IN BOOL bAlertable) -{ - PLARGE_INTEGER TimePtr; - LARGE_INTEGER Time; - PHANDLE HandleBuffer; - HANDLE Handle[8]; - DWORD i; - NTSTATUS Status; - - /* Check if we have more handles then we locally optimize */ - if (nCount > 8) - { - /* Allocate a buffer for them */ - HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - nCount * sizeof(HANDLE)); - if (!HandleBuffer) - { - /* No buffer, fail the wait */ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return WAIT_FAILED; - } - } - else - { - /* Otherwise, use our local buffer */ - HandleBuffer = Handle; - } - - /* Copy the handles into our buffer and loop them all */ - RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE)); - for (i = 0; i < nCount; i++) - { - /* Check what kind of handle this is */ - HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]); - - /* Check for console handle */ - if ((IsConsoleHandle(HandleBuffer[i])) && - (VerifyConsoleIoHandle(HandleBuffer[i]))) - { - /* Get the real wait handle */ - HandleBuffer[i] = GetConsoleInputWaitHandle(); - } - } - - /* Check if this is an infinite wait */ - if (dwMilliseconds == INFINITE) - { - /* Under NT, this means no timer argument */ - TimePtr = NULL; - } - else - { - /* Otherwise, convert the time to NT Format */ - Time.QuadPart = UInt32x32To64(-10000, dwMilliseconds); - TimePtr = &Time; - } - - /* Start wait loop */ - do - { - /* Do the wait */ - Status = NtWaitForMultipleObjects(nCount, - HandleBuffer, - bWaitAll ? WaitAll : WaitAny, - (BOOLEAN)bAlertable, - TimePtr); - if (!NT_SUCCESS(Status)) - { - /* Wait failed */ - SetLastErrorByStatus (Status); - return WAIT_FAILED; - } - } while ((Status == STATUS_ALERTED) && (bAlertable)); - - /* Check if we didn't use our local buffer */ - if (HandleBuffer != Handle) - { - /* Free the allocated one */ - RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); - } - - /* Return wait status */ - return Status; -} - -/* - * @implemented - */ -DWORD -WINAPI -SignalObjectAndWait(IN HANDLE hObjectToSignal, - IN HANDLE hObjectToWaitOn, - IN DWORD dwMilliseconds, - IN BOOL bAlertable) -{ - PLARGE_INTEGER TimePtr; - LARGE_INTEGER Time; - NTSTATUS Status; - - /* Get real handle */ - hObjectToWaitOn = TranslateStdHandle(hObjectToWaitOn); - - /* Check for console handle */ - if ((IsConsoleHandle(hObjectToWaitOn)) && - (VerifyConsoleIoHandle(hObjectToWaitOn))) - { - /* Get the real wait handle */ - hObjectToWaitOn = GetConsoleInputWaitHandle(); - } - - /* Check if this is an infinite wait */ - if (dwMilliseconds == INFINITE) - { - /* Under NT, this means no timer argument */ - TimePtr = NULL; - } - else - { - /* Otherwise, convert the time to NT Format */ - Time.QuadPart = UInt32x32To64(-10000, dwMilliseconds); - TimePtr = &Time; - } - - /* Start wait loop */ - do - { - /* Do the wait */ - Status = NtSignalAndWaitForSingleObject(hObjectToSignal, - hObjectToWaitOn, - (BOOLEAN)bAlertable, - TimePtr); - if (!NT_SUCCESS(Status)) - { - /* The wait failed */ - SetLastErrorByStatus (Status); - return WAIT_FAILED; - } - } while ((Status == STATUS_ALERTED) && (bAlertable)); - - /* Return wait status */ - return Status; -} - -/* EOF */ diff --git a/dll/win32/kernel32/thread/amd64/fiber.S b/dll/win32/kernel32/thread/amd64/fiber.S deleted file mode 100644 index 09ea635d23c..00000000000 --- a/dll/win32/kernel32/thread/amd64/fiber.S +++ /dev/null @@ -1,19 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/thread/i386/fiber.S - * PURPOSE: Fiber context switch code for the x86 architecture - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - * KJK::Hyperion - */ - -#include - - -PUBLIC SwitchToFiber - -SwitchToFiber: - /* FIXME: TODO */ - ret 4 - -END diff --git a/dll/win32/kernel32/thread/fls.c b/dll/win32/kernel32/thread/fls.c deleted file mode 100644 index d5e4e612779..00000000000 --- a/dll/win32/kernel32/thread/fls.c +++ /dev/null @@ -1,122 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/thread/fls.c - * PURPOSE: Fiber local storage functions - * PROGRAMMER: KJK::Hyperion - * - * UPDATE HISTORY: - * 28/05/2003 - created. Stubs only - * - */ - -#include - -#include - -/* - * @unimplemented - */ -DWORD -WINAPI -FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback) -{ - (void)lpCallback; - - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FLS_OUT_OF_INDEXES; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -FlsFree(DWORD dwFlsIndex) -{ - (void)dwFlsIndex; - - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - - -/* - * @implemented - */ -PVOID -WINAPI -FlsGetValue(DWORD dwFlsIndex) -{ - PVOID *ppFlsSlots; - PVOID pRetVal; - - if(dwFlsIndex >= 128) goto l_InvalidParam; - - ppFlsSlots = NtCurrentTeb()->FlsData; - - if(ppFlsSlots == NULL) goto l_InvalidParam; - - SetLastError(0); - pRetVal = ppFlsSlots[dwFlsIndex + 2]; - - return pRetVal; - -l_InvalidParam: - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; -} - - -/* - * @implemented - */ -BOOL -WINAPI -FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData) -{ - PVOID *ppFlsSlots; - TEB *pTeb = NtCurrentTeb(); - - if(dwFlsIndex >= 128) goto l_InvalidParam; - - ppFlsSlots = pTeb->FlsData; - - if (ppFlsSlots == NULL) - { - PEB *pPeb = pTeb->ProcessEnvironmentBlock; - - ppFlsSlots = RtlAllocateHeap(pPeb->ProcessHeap, - HEAP_ZERO_MEMORY, - (128 + 2) * sizeof(PVOID)); - if(ppFlsSlots == NULL) goto l_OutOfMemory; - - pTeb->FlsData = ppFlsSlots; - - RtlAcquirePebLock(); - - /* TODO: initialization */ - - RtlReleasePebLock(); - } - - ppFlsSlots[dwFlsIndex + 2] = lpFlsData; - - return TRUE; - -l_OutOfMemory: - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto l_Fail; - -l_InvalidParam: - SetLastError(ERROR_INVALID_PARAMETER); - -l_Fail: - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/kernel32/thread/tls.c b/dll/win32/kernel32/thread/tls.c deleted file mode 100644 index be7fa0217b7..00000000000 --- a/dll/win32/kernel32/thread/tls.c +++ /dev/null @@ -1,196 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/thread/tls.c - * PURPOSE: Thread functions - * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - * Tls functions are modified from WINE - * UPDATE HISTORY: - * Created 01/11/98 - */ - -/* INCLUDES ******************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -DWORD -WINAPI -TlsAlloc(VOID) -{ - ULONG Index; - - RtlAcquirePebLock(); - - /* Try to get regular TEB slot. */ - Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsBitmap, 1, 0); - if (Index == ~0U) - { - /* If it fails, try to find expansion TEB slot. */ - Index = RtlFindClearBitsAndSet(NtCurrentPeb()->TlsExpansionBitmap, 1, 0); - if (Index != ~0U) - { - if (NtCurrentTeb()->TlsExpansionSlots == NULL) - { - NtCurrentTeb()->TlsExpansionSlots = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - TLS_EXPANSION_SLOTS * - sizeof(PVOID)); - } - - if (NtCurrentTeb()->TlsExpansionSlots == NULL) - { - RtlClearBits(NtCurrentPeb()->TlsExpansionBitmap, Index, 1); - Index = ~0; - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - else - { - /* Clear the value. */ - NtCurrentTeb()->TlsExpansionSlots[Index] = 0; - Index += TLS_MINIMUM_AVAILABLE; - } - } - else - { - SetLastError(ERROR_NO_MORE_ITEMS); - } - } - else - { - /* Clear the value. */ - NtCurrentTeb()->TlsSlots[Index] = 0; - } - - RtlReleasePebLock(); - - return Index; -} - -/* - * @implemented - */ -BOOL -WINAPI -TlsFree(DWORD Index) -{ - BOOL BitSet; - - if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) - { - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return FALSE; - } - - RtlAcquirePebLock(); - - if (Index >= TLS_MINIMUM_AVAILABLE) - { - BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsExpansionBitmap, - Index - TLS_MINIMUM_AVAILABLE, - 1); - - if (BitSet) - RtlClearBits(NtCurrentPeb()->TlsExpansionBitmap, - Index - TLS_MINIMUM_AVAILABLE, - 1); - } - else - { - BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsBitmap, Index, 1); - if (BitSet) - RtlClearBits(NtCurrentPeb()->TlsBitmap, Index, 1); - } - - if (BitSet) - { - /* Clear the TLS cells (slots) in all threads of the current process. */ - NtSetInformationThread(NtCurrentThread(), - ThreadZeroTlsCell, - &Index, - sizeof(DWORD)); - } - else - { - SetLastError(ERROR_INVALID_PARAMETER); - } - - RtlReleasePebLock(); - - return BitSet; -} - -/* - * @implemented - */ -LPVOID -WINAPI -TlsGetValue(DWORD Index) -{ - if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) - { - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return NULL; - } - - SetLastError(NO_ERROR); - - if (Index >= TLS_MINIMUM_AVAILABLE) - { - /* The expansion slots are allocated on demand, so check for it. */ - if (NtCurrentTeb()->TlsExpansionSlots == NULL) - return NULL; - return NtCurrentTeb()->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE]; - } - else - { - return NtCurrentTeb()->TlsSlots[Index]; - } -} - -/* - * @implemented - */ -BOOL -WINAPI -TlsSetValue(DWORD Index, - LPVOID Value) -{ - if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) - { - SetLastErrorByStatus(STATUS_INVALID_PARAMETER); - return FALSE; - } - - if (Index >= TLS_MINIMUM_AVAILABLE) - { - if (NtCurrentTeb()->TlsExpansionSlots == NULL) - { - NtCurrentTeb()->TlsExpansionSlots = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - TLS_EXPANSION_SLOTS * - sizeof(PVOID)); - - if (NtCurrentTeb()->TlsExpansionSlots == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - } - - NtCurrentTeb()->TlsExpansionSlots[Index - TLS_MINIMUM_AVAILABLE] = Value; - } - else - { - NtCurrentTeb()->TlsSlots[Index] = Value; - } - - return TRUE; -} diff --git a/dll/win32/kernel32/wine/actctx.c b/dll/win32/kernel32/wine/actctx.c new file mode 100644 index 00000000000..516dcb5d9c8 --- /dev/null +++ b/dll/win32/kernel32/wine/actctx.c @@ -0,0 +1,282 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/actctx.c + * PURPOSE: Activation contexts + * PROGRAMMERS: Jacek Caban for CodeWeavers + * Eric Pouech + * Jon Griffiths + * Dmitry Chapyshev (dmitry@reactos.org) + * Samuel Serapión + */ + +/* synched with wine 1.1.26 */ + +#include +#define NDEBUG +#include +DEBUG_CHANNEL(actctx); + +#define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa) + +/*********************************************************************** + * CreateActCtxA (KERNEL32.@) + * + * Create an activation context. + */ +HANDLE WINAPI CreateActCtxA(PCACTCTXA pActCtx) +{ + ACTCTXW actw; + SIZE_T len; + HANDLE ret = INVALID_HANDLE_VALUE; + LPWSTR src = NULL, assdir = NULL, resname = NULL, appname = NULL; + + TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0); + + if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + actw.cbSize = sizeof(actw); + actw.dwFlags = pActCtx->dwFlags; + if (pActCtx->lpSource) + { + len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpSource, -1, NULL, 0); + src = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!src) return INVALID_HANDLE_VALUE; + MultiByteToWideChar(CP_ACP, 0, pActCtx->lpSource, -1, src, len); + } + actw.lpSource = src; + + if (actw.dwFlags & ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID) + actw.wProcessorArchitecture = pActCtx->wProcessorArchitecture; + if (actw.dwFlags & ACTCTX_FLAG_LANGID_VALID) + actw.wLangId = pActCtx->wLangId; + if (actw.dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) + { + len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpAssemblyDirectory, -1, NULL, 0); + assdir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!assdir) goto done; + MultiByteToWideChar(CP_ACP, 0, pActCtx->lpAssemblyDirectory, -1, assdir, len); + actw.lpAssemblyDirectory = assdir; + } + if (actw.dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) + { + if ((ULONG_PTR)pActCtx->lpResourceName >> 16) + { + len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpResourceName, -1, NULL, 0); + resname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!resname) goto done; + MultiByteToWideChar(CP_ACP, 0, pActCtx->lpResourceName, -1, resname, len); + actw.lpResourceName = resname; + } + else actw.lpResourceName = (LPCWSTR)pActCtx->lpResourceName; + } + if (actw.dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID) + { + len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpApplicationName, -1, NULL, 0); + appname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!appname) goto done; + MultiByteToWideChar(CP_ACP, 0, pActCtx->lpApplicationName, -1, appname, len); + actw.lpApplicationName = appname; + } + if (actw.dwFlags & ACTCTX_FLAG_HMODULE_VALID) + actw.hModule = pActCtx->hModule; + + ret = CreateActCtxW(&actw); + +done: + HeapFree(GetProcessHeap(), 0, src); + HeapFree(GetProcessHeap(), 0, assdir); + HeapFree(GetProcessHeap(), 0, resname); + HeapFree(GetProcessHeap(), 0, appname); + return ret; +} + +/*********************************************************************** + * CreateActCtxW (KERNEL32.@) + * + * Create an activation context. + */ +HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx) +{ + NTSTATUS status; + HANDLE hActCtx; + + TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0); + + if ((status = RtlCreateActivationContext(&hActCtx, (PVOID*)pActCtx))) + { + SetLastError(RtlNtStatusToDosError(status)); + return INVALID_HANDLE_VALUE; + } + return hActCtx; +} + +/*********************************************************************** + * ActivateActCtx (KERNEL32.@) + * + * Activate an activation context. + */ +BOOL WINAPI ActivateActCtx(HANDLE hActCtx, ULONG_PTR *ulCookie) +{ + NTSTATUS status; + + if ((status = RtlActivateActivationContext( 0, hActCtx, ulCookie ))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; +} + +/*********************************************************************** + * DeactivateActCtx (KERNEL32.@) + * + * Deactivate an activation context. + */ +BOOL WINAPI DeactivateActCtx(DWORD dwFlags, ULONG_PTR ulCookie) +{ + RtlDeactivateActivationContext( dwFlags, ulCookie ); + return TRUE; +} + +/*********************************************************************** + * GetCurrentActCtx (KERNEL32.@) + * + * Get the current activation context. + */ +BOOL WINAPI GetCurrentActCtx(HANDLE* phActCtx) +{ + NTSTATUS status; + + if ((status = RtlGetActiveActivationContext(phActCtx))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; +} + +/*********************************************************************** + * AddRefActCtx (KERNEL32.@) + * + * Add a reference to an activation context. + */ +void WINAPI AddRefActCtx(HANDLE hActCtx) +{ + RtlAddRefActivationContext(hActCtx); +} + +/*********************************************************************** + * ReleaseActCtx (KERNEL32.@) + * + * Release a reference to an activation context. + */ +void WINAPI ReleaseActCtx(HANDLE hActCtx) +{ + RtlReleaseActivationContext(hActCtx); +} + +/*********************************************************************** + * ZombifyActCtx (KERNEL32.@) + * + * Release a reference to an activation context. + */ +BOOL WINAPI ZombifyActCtx(HANDLE hActCtx) +{ + FIXME("%p\n", hActCtx); + if (hActCtx != ACTCTX_FAKE_HANDLE) + return FALSE; + return TRUE; +} + +/*********************************************************************** + * FindActCtxSectionStringA (KERNEL32.@) + * + * Find information about a string in an activation context. + */ +BOOL WINAPI FindActCtxSectionStringA(DWORD dwFlags, const GUID* lpExtGuid, + ULONG ulId, LPCSTR lpSearchStr, + PACTCTX_SECTION_KEYED_DATA pInfo) +{ + LPWSTR search_str; + DWORD len; + BOOL ret; + + TRACE("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid), + ulId, debugstr_a(lpSearchStr), pInfo); + + if (!lpSearchStr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + len = MultiByteToWideChar(CP_ACP, 0, lpSearchStr, -1, NULL, 0); + search_str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpSearchStr, -1, search_str, len); + + ret = FindActCtxSectionStringW(dwFlags, lpExtGuid, ulId, search_str, pInfo); + + HeapFree(GetProcessHeap(), 0, search_str); + return ret; +} + +/*********************************************************************** + * FindActCtxSectionStringW (KERNEL32.@) + * + * Find information about a string in an activation context. + */ +BOOL WINAPI FindActCtxSectionStringW(DWORD dwFlags, const GUID* lpExtGuid, + ULONG ulId, LPCWSTR lpSearchStr, + PACTCTX_SECTION_KEYED_DATA pInfo) +{ + UNICODE_STRING us; + NTSTATUS status; + + RtlInitUnicodeString(&us, lpSearchStr); + if ((status = RtlFindActivationContextSectionString(dwFlags, lpExtGuid, ulId, &us, pInfo))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; +} + +/*********************************************************************** + * FindActCtxSectionGuid (KERNEL32.@) + * + * Find information about a GUID in an activation context. + */ +BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID* lpExtGuid, + ULONG ulId, const GUID* lpSearchGuid, + PACTCTX_SECTION_KEYED_DATA pInfo) +{ + FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid), + ulId, debugstr_guid(lpSearchGuid), pInfo); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/*********************************************************************** + * QueryActCtxW (KERNEL32.@) + * + * Get information about an activation context. + */ +BOOL WINAPI QueryActCtxW(DWORD dwFlags, HANDLE hActCtx, PVOID pvSubInst, + ULONG ulClass, PVOID pvBuff, SIZE_T cbBuff, + SIZE_T *pcbLen) +{ + NTSTATUS status; + + if ((status = RtlQueryInformationActivationContext( dwFlags, hActCtx, pvSubInst, ulClass, + pvBuff, cbBuff, pcbLen ))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; +} diff --git a/dll/win32/kernel32/wine/comm.c b/dll/win32/kernel32/wine/comm.c new file mode 100644 index 00000000000..5fb76ac948d --- /dev/null +++ b/dll/win32/kernel32/wine/comm.c @@ -0,0 +1,1471 @@ +/* + * DEC 93 Erik Bos + * + * Copyright 1996 Marcus Meissner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//#include "config.h" +//#include "wine/port.h" + +#include +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winioctl.h" +#include "winternl.h" +//#include "ddk/ntddser.h" + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; +#undef SERIAL_LSRMST_ESCAPE +#undef SERIAL_LSRMST_LSR_DATA +#undef SERIAL_LSRMST_LSR_NODATA +#undef SERIAL_LSRMST_MST +#undef SERIAL_IOC_FCR_FIFO_ENABLE +#undef SERIAL_IOC_FCR_RCVR_RESET +#undef SERIAL_IOC_FCR_XMIT_RESET +#undef SERIAL_IOC_FCR_DMA_MODE +#undef SERIAL_IOC_FCR_RES1 +#undef SERIAL_IOC_FCR_RES2 +#undef SERIAL_IOC_FCR_RCVR_TRIGGER_LSB +#undef SERIAL_IOC_FCR_RCVR_TRIGGER_MSB +#undef SERIAL_IOC_MCR_DTR +#undef SERIAL_IOC_MCR_RTS +#undef SERIAL_IOC_MCR_OUT1 +#undef SERIAL_IOC_MCR_OUT2 +#undef SERIAL_IOC_MCR_LOOP +#undef IOCTL_SERIAL_LSRMST_INSERT +#include + +#include "wine/unicode.h" + +#include "wine/debug.h" + +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap +WINE_DEFAULT_DEBUG_CHANNEL(comm); + +/*********************************************************************** + * COMM_Parse* (Internal) + * + * The following COMM_Parse* functions are used by the BuildCommDCB + * functions to help parse the various parts of the device control string. + */ +static LPCWSTR COMM_ParseStart(LPCWSTR ptr) +{ + static const WCHAR comW[] = {'C','O','M',0}; + + /* The device control string may optionally start with "COMx" followed + by an optional ':' and spaces. */ + if(!strncmpiW(ptr, comW, 3)) + { + ptr += 3; + + /* Allow any com port above 0 as Win 9x does (NT only allows + values for com ports which are actually present) */ + if(*ptr < '1' || *ptr > '9') + return NULL; + + /* Advance pointer past port number */ + while(*ptr >= '0' && *ptr <= '9') ptr++; + + /* The com port number must be followed by a ':' or ' ' */ + if(*ptr != ':' && *ptr != ' ') + return NULL; + + /* Advance pointer to beginning of next parameter */ + while(*ptr == ' ') ptr++; + if(*ptr == ':') + { + ptr++; + while(*ptr == ' ') ptr++; + } + } + /* The device control string must not start with a space. */ + else if(*ptr == ' ') + return NULL; + + return ptr; +} + +static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber) +{ + if(*ptr < '0' || *ptr > '9') return NULL; + *lpnumber = strtoulW(ptr, NULL, 10); + while(*ptr >= '0' && *ptr <= '9') ptr++; + return ptr; +} + +static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity) +{ + /* Contrary to what you might expect, Windows only sets the Parity + member of DCB and not fParity even when parity is specified in the + device control string */ + + switch(toupperW(*ptr++)) + { + case 'E': + *lpparity = EVENPARITY; + break; + case 'M': + *lpparity = MARKPARITY; + break; + case 'N': + *lpparity = NOPARITY; + break; + case 'O': + *lpparity = ODDPARITY; + break; + case 'S': + *lpparity = SPACEPARITY; + break; + default: + return NULL; + } + + return ptr; +} + +static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize) +{ + DWORD temp; + + if(!(ptr = COMM_ParseNumber(ptr, &temp))) + return NULL; + + if(temp >= 5 && temp <= 8) + { + *lpbytesize = temp; + return ptr; + } + else + return NULL; +} + +static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits) +{ + DWORD temp; + static const WCHAR stopbits15W[] = {'1','.','5',0}; + + if(!strncmpW(stopbits15W, ptr, 3)) + { + ptr += 3; + *lpstopbits = ONE5STOPBITS; + } + else + { + if(!(ptr = COMM_ParseNumber(ptr, &temp))) + return NULL; + + if(temp == 1) + *lpstopbits = ONESTOPBIT; + else if(temp == 2) + *lpstopbits = TWOSTOPBITS; + else + return NULL; + } + + return ptr; +} + +static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff) +{ + static const WCHAR onW[] = {'o','n',0}; + static const WCHAR offW[] = {'o','f','f',0}; + + if(!strncmpiW(onW, ptr, 2)) + { + ptr += 2; + *lponoff = 1; + } + else if(!strncmpiW(offW, ptr, 3)) + { + ptr += 3; + *lponoff = 0; + } + else + return NULL; + + return ptr; +} + +/*********************************************************************** + * COMM_BuildOldCommDCB (Internal) + * + * Build a DCB using the old style settings string eg: "96,n,8,1" + */ +static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb) +{ + WCHAR last = 0; + + if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate))) + return FALSE; + + switch(lpdcb->BaudRate) + { + case 11: + case 30: + case 60: + lpdcb->BaudRate *= 10; + break; + case 12: + case 24: + case 48: + case 96: + lpdcb->BaudRate *= 100; + break; + case 19: + lpdcb->BaudRate = 19200; + break; + } + + while(*device == ' ') device++; + if(*device++ != ',') return FALSE; + while(*device == ' ') device++; + + if(!(device = COMM_ParseParity(device, &lpdcb->Parity))) + return FALSE; + + while(*device == ' ') device++; + if(*device++ != ',') return FALSE; + while(*device == ' ') device++; + + if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize))) + return FALSE; + + while(*device == ' ') device++; + if(*device++ != ',') return FALSE; + while(*device == ' ') device++; + + if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits))) + return FALSE; + + /* The last parameter for flow control is optional. */ + while(*device == ' ') device++; + if(*device == ',') + { + device++; + while(*device == ' ') device++; + if(*device) last = toupperW(*device++); + while(*device == ' ') device++; + } + + /* Win NT sets the flow control members based on (or lack of) the last + parameter. Win 9x does not set these members. */ + switch(last) + { + case 0: + lpdcb->fInX = FALSE; + lpdcb->fOutX = FALSE; + lpdcb->fOutxCtsFlow = FALSE; + lpdcb->fOutxDsrFlow = FALSE; + lpdcb->fDtrControl = DTR_CONTROL_ENABLE; + lpdcb->fRtsControl = RTS_CONTROL_ENABLE; + break; + case 'X': + lpdcb->fInX = TRUE; + lpdcb->fOutX = TRUE; + lpdcb->fOutxCtsFlow = FALSE; + lpdcb->fOutxDsrFlow = FALSE; + lpdcb->fDtrControl = DTR_CONTROL_ENABLE; + lpdcb->fRtsControl = RTS_CONTROL_ENABLE; + break; + case 'P': + lpdcb->fInX = FALSE; + lpdcb->fOutX = FALSE; + lpdcb->fOutxCtsFlow = TRUE; + lpdcb->fOutxDsrFlow = TRUE; + lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; + lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; + break; + default: + return FALSE; + } + + /* This should be the end of the string. */ + if(*device) return FALSE; + + return TRUE; +} + +/*********************************************************************** + * COMM_BuildNewCommDCB (Internal) + * + * Build a DCB using the new style settings string. + * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on" + */ +static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts) +{ + DWORD temp; + BOOL baud = FALSE, stop = FALSE; + static const WCHAR baudW[] = {'b','a','u','d','=',0}; + static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0}; + static const WCHAR dataW[] = {'d','a','t','a','=',0}; + static const WCHAR stopW[] = {'s','t','o','p','=',0}; + static const WCHAR toW[] = {'t','o','=',0}; + static const WCHAR xonW[] = {'x','o','n','=',0}; + static const WCHAR odsrW[] = {'o','d','s','r','=',0}; + static const WCHAR octsW[] = {'o','c','t','s','=',0}; + static const WCHAR dtrW[] = {'d','t','r','=',0}; + static const WCHAR rtsW[] = {'r','t','s','=',0}; + static const WCHAR idsrW[] = {'i','d','s','r','=',0}; + + while(*device) + { + while(*device == ' ') device++; + + if(!strncmpiW(baudW, device, 5)) + { + baud = TRUE; + + if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate))) + return FALSE; + } + else if(!strncmpiW(parityW, device, 7)) + { + if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity))) + return FALSE; + } + else if(!strncmpiW(dataW, device, 5)) + { + if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize))) + return FALSE; + } + else if(!strncmpiW(stopW, device, 5)) + { + stop = TRUE; + + if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits))) + return FALSE; + } + else if(!strncmpiW(toW, device, 3)) + { + if(!(device = COMM_ParseOnOff(device + 3, &temp))) + return FALSE; + + lptimeouts->ReadIntervalTimeout = 0; + lptimeouts->ReadTotalTimeoutMultiplier = 0; + lptimeouts->ReadTotalTimeoutConstant = 0; + lptimeouts->WriteTotalTimeoutMultiplier = 0; + lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0; + } + else if(!strncmpiW(xonW, device, 4)) + { + if(!(device = COMM_ParseOnOff(device + 4, &temp))) + return FALSE; + + lpdcb->fOutX = temp; + lpdcb->fInX = temp; + } + else if(!strncmpiW(odsrW, device, 5)) + { + if(!(device = COMM_ParseOnOff(device + 5, &temp))) + return FALSE; + + lpdcb->fOutxDsrFlow = temp; + } + else if(!strncmpiW(octsW, device, 5)) + { + if(!(device = COMM_ParseOnOff(device + 5, &temp))) + return FALSE; + + lpdcb->fOutxCtsFlow = temp; + } + else if(!strncmpiW(dtrW, device, 4)) + { + if(!(device = COMM_ParseOnOff(device + 4, &temp))) + return FALSE; + + lpdcb->fDtrControl = temp; + } + else if(!strncmpiW(rtsW, device, 4)) + { + if(!(device = COMM_ParseOnOff(device + 4, &temp))) + return FALSE; + + lpdcb->fRtsControl = temp; + } + else if(!strncmpiW(idsrW, device, 5)) + { + if(!(device = COMM_ParseOnOff(device + 5, &temp))) + return FALSE; + + /* Win NT sets the fDsrSensitivity member based on the + idsr parameter. Win 9x sets fOutxDsrFlow instead. */ + lpdcb->fDsrSensitivity = temp; + } + else + return FALSE; + + /* After the above parsing, the next character (if not the end of + the string) should be a space */ + if(*device && *device != ' ') + return FALSE; + } + + /* If stop bits were not specified, a default is always supplied. */ + if(!stop) + { + if(baud && lpdcb->BaudRate == 110) + lpdcb->StopBits = TWOSTOPBITS; + else + lpdcb->StopBits = ONESTOPBIT; + } + + return TRUE; +} + +/************************************************************************** + * BuildCommDCBA (KERNEL32.@) + * + * Updates a device control block data structure with values from an + * ascii device control string. The device control string has two forms + * normal and extended, it must be exclusively in one or the other form. + * + * RETURNS + * + * True on success, false on a malformed control string. + */ +BOOL WINAPI BuildCommDCBA( + LPCSTR device, /* [in] The ascii device control string used to update the DCB. */ + LPDCB lpdcb) /* [out] The device control block to be updated. */ +{ + return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL); +} + +/************************************************************************** + * BuildCommDCBAndTimeoutsA (KERNEL32.@) + * + * Updates a device control block data structure with values from an + * ascii device control string. Taking timeout values from a timeouts + * struct if desired by the control string. + * + * RETURNS + * + * True on success, false bad handles etc. + */ +BOOL WINAPI BuildCommDCBAndTimeoutsA( + LPCSTR device, /* [in] The ascii device control string. */ + LPDCB lpdcb, /* [out] The device control block to be updated. */ + LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */ +{ + BOOL ret = FALSE; + UNICODE_STRING deviceW; + + TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts); + if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device); + else deviceW.Buffer = NULL; + + if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts); + + RtlFreeUnicodeString(&deviceW); + return ret; +} + +/************************************************************************** + * BuildCommDCBAndTimeoutsW (KERNEL32.@) + * + * Updates a device control block data structure with values from a + * unicode device control string. Taking timeout values from a timeouts + * struct if desired by the control string. + * + * RETURNS + * + * True on success, false bad handles etc + */ +BOOL WINAPI BuildCommDCBAndTimeoutsW( + LPCWSTR devid, /* [in] The unicode device control string. */ + LPDCB lpdcb, /* [out] The device control block to be updated. */ + LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */ +{ + DCB dcb; + COMMTIMEOUTS timeouts; + BOOL result; + LPCWSTR ptr = devid; + + TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts); + + memset(&timeouts, 0, sizeof timeouts); + + /* Set DCBlength. (Windows NT does not do this, but 9x does) */ + lpdcb->DCBlength = sizeof(DCB); + + /* Make a copy of the original data structures to work with since if + if there is an error in the device control string the originals + should not be modified (except possibly DCBlength) */ + dcb = *lpdcb; + if(lptimeouts) timeouts = *lptimeouts; + + ptr = COMM_ParseStart(ptr); + + if(ptr == NULL) + result = FALSE; + else if(strchrW(ptr, ',')) + result = COMM_BuildOldCommDCB(ptr, &dcb); + else + result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts); + + if(result) + { + *lpdcb = dcb; + if(lptimeouts) *lptimeouts = timeouts; + return TRUE; + } + else + { + WARN("Invalid device control string: %s\n", debugstr_w(devid)); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +} + +/************************************************************************** + * BuildCommDCBW (KERNEL32.@) + * + * Updates a device control block structure with values from an + * unicode device control string. The device control string has two forms + * normal and extended, it must be exclusively in one or the other form. + * + * RETURNS + * + * True on success, false on a malformed control string. + */ +BOOL WINAPI BuildCommDCBW( + LPCWSTR devid, /* [in] The unicode device control string. */ + LPDCB lpdcb) /* [out] The device control block to be updated. */ +{ + return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL); +} + +/***************************************************************************** + * SetCommBreak (KERNEL32.@) + * + * Halts the transmission of characters to a communications device. + * + * PARAMS + * handle [in] The communications device to suspend + * + * RETURNS + * + * True on success, and false if the communications device could not be found, + * the control is not supported. + * + * BUGS + * + * Only TIOCSBRK and TIOCCBRK are supported. + */ +BOOL WINAPI SetCommBreak(HANDLE handle) +{ + DWORD dwBytesReturned; + return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL); +} + +/***************************************************************************** + * ClearCommBreak (KERNEL32.@) + * + * Resumes character transmission from a communication device. + * + * PARAMS + * + * handle [in] The halted communication device whose character transmission is to be resumed + * + * RETURNS + * + * True on success and false if the communications device could not be found. + * + * BUGS + * + * Only TIOCSBRK and TIOCCBRK are supported. + */ +BOOL WINAPI ClearCommBreak(HANDLE handle) +{ + DWORD dwBytesReturned; + return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL); +} + +/***************************************************************************** + * EscapeCommFunction (KERNEL32.@) + * + * Directs a communication device to perform an extended function. + * + * PARAMS + * + * handle [in] The communication device to perform the extended function + * nFunction [in] The extended function to be performed + * + * RETURNS + * + * True or requested data on successful completion of the command, + * false if the device is not present cannot execute the command + * or the command failed. + */ +BOOL WINAPI EscapeCommFunction(HANDLE handle, DWORD func) +{ + DWORD ioc; + DWORD dwBytesReturned; + + switch (func) + { + case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break; + case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break; + case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break; + case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break; + case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break; + case SETXON: ioc = IOCTL_SERIAL_SET_XON; break; + case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break; + case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break; + case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break; + default: + ERR("Unknown function code (%u)\n", func); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, &dwBytesReturned, NULL); +} + +/******************************************************************** + * PurgeComm (KERNEL32.@) + * + * Terminates pending operations and/or discards buffers on a + * communication resource. + * + * PARAMS + * + * handle [in] The communication resource to be purged + * flags [in] Flags for clear pending/buffer on input/output + * + * RETURNS + * + * True on success and false if the communications handle is bad. + */ +BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags) +{ + DWORD dwBytesReturned; + return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags), + NULL, 0, &dwBytesReturned, NULL); +} + +/***************************************************************************** + * ClearCommError (KERNEL32.@) + * + * Enables further I/O operations on a communications resource after + * supplying error and current status information. + * + * PARAMS + * + * handle [in] The communication resource with the error + * errors [out] Flags indicating error the resource experienced + * lpStat [out] The status of the communication resource + * RETURNS + * + * True on success, false if the communication resource handle is bad. + */ +BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat) +{ + SERIAL_STATUS ss; + DWORD dwBytesReturned; + + if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, + &ss, sizeof(ss), &dwBytesReturned, NULL)) + return FALSE; + + if (errors) + { + *errors = 0; + if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK; + if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME; + if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN; + if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER; + if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY; + } + + if (lpStat) + { + memset(lpStat, 0, sizeof(*lpStat)); + + if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE; + if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE; + if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE; + if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE; + if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE; + if (ss.EofReceived) lpStat->fEof = TRUE; + if (ss.WaitForImmediate) lpStat->fTxim = TRUE; + lpStat->cbInQue = ss.AmountInInQueue; + lpStat->cbOutQue = ss.AmountInOutQueue; + } + return TRUE; +} + +/***************************************************************************** + * SetupComm (KERNEL32.@) + * + * Called after CreateFile to hint to the communication resource to use + * specified sizes for input and output buffers rather than the default values. + * + * PARAMS + * handle [in] The just created communication resource handle + * insize [in] The suggested size of the communication resources input buffer in bytes + * outsize [in] The suggested size of the communication resources output buffer in bytes + * + * RETURNS + * + * True if successful, false if the communications resource handle is bad. + * + * BUGS + * + * Stub. + */ +BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize) +{ + SERIAL_QUEUE_SIZE sqs; + DWORD dwBytesReturned; + + sqs.InSize = insize; + sqs.OutSize = outsize; + return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE, + &sqs, sizeof(sqs), NULL, 0, &dwBytesReturned, NULL); +} + +/***************************************************************************** + * GetCommMask (KERNEL32.@) + * + * Obtain the events associated with a communication device that will cause + * a call WaitCommEvent to return. + * + * PARAMS + * + * handle [in] The communications device + * evtmask [out] The events which cause WaitCommEvent to return + * + * RETURNS + * + * True on success, fail on bad device handle etc. + */ +BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask) +{ + DWORD dwBytesReturned; + TRACE("handle %p, mask %p\n", handle, evtmask); + return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK, + NULL, 0, evtmask, sizeof(*evtmask), &dwBytesReturned, NULL); +} + +/***************************************************************************** + * SetCommMask (KERNEL32.@) + * + * There be some things we need to hear about yon there communications device. + * (Set which events associated with a communication device should cause + * a call WaitCommEvent to return.) + * + * PARAMS + * + * handle [in] The communications device + * evtmask [in] The events that are to be monitored + * + * RETURNS + * + * True on success, false on bad handle etc. + */ +BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask) +{ + DWORD dwBytesReturned; + TRACE("handle %p, mask %x\n", handle, evtmask); + return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK, + &evtmask, sizeof(evtmask), NULL, 0, &dwBytesReturned, NULL); +} + +static void dump_dcb(const DCB* lpdcb) +{ + TRACE("bytesize=%d baudrate=%d fParity=%d Parity=%d stopbits=%d\n", + lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity, + (lpdcb->StopBits == ONESTOPBIT) ? 1 : + (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0); + TRACE("%sIXON %sIXOFF\n", (lpdcb->fOutX) ? "" : "~", (lpdcb->fInX) ? "" : "~"); + TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl); + TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl); + if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE) + TRACE("CRTSCTS\n"); + else + TRACE("~CRTSCTS\n"); +} + +/***************************************************************************** + * SetCommState (KERNEL32.@) + * + * Re-initializes all hardware and control settings of a communications device, + * with values from a device control block without affecting the input and output + * queues. + * + * PARAMS + * + * handle [in] The communications device + * lpdcb [out] The device control block + * + * RETURNS + * + * True on success, false on failure, e.g., if the XonChar is equal to the XoffChar. + */ +BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb) +{ + SERIAL_BAUD_RATE sbr; + SERIAL_LINE_CONTROL slc; + SERIAL_HANDFLOW shf; + SERIAL_CHARS sc; + DWORD dwBytesReturned; + + if (lpdcb == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + dump_dcb(lpdcb); + + sbr.BaudRate = lpdcb->BaudRate; + + slc.StopBits = lpdcb->StopBits; + slc.Parity = lpdcb->Parity; + slc.WordLength = lpdcb->ByteSize; + + shf.ControlHandShake = 0; + shf.FlowReplace = 0; + if (lpdcb->fOutxCtsFlow) shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE; + if (lpdcb->fOutxDsrFlow) shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE; + switch (lpdcb->fDtrControl) + { + case DTR_CONTROL_DISABLE: break; + case DTR_CONTROL_ENABLE: shf.ControlHandShake |= SERIAL_DTR_CONTROL; break; + case DTR_CONTROL_HANDSHAKE: shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + switch (lpdcb->fRtsControl) + { + case RTS_CONTROL_DISABLE: break; + case RTS_CONTROL_ENABLE: shf.FlowReplace |= SERIAL_RTS_CONTROL; break; + case RTS_CONTROL_HANDSHAKE: shf.FlowReplace |= SERIAL_RTS_HANDSHAKE; break; + case RTS_CONTROL_TOGGLE: shf.FlowReplace |= SERIAL_RTS_CONTROL | + SERIAL_RTS_HANDSHAKE; break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (lpdcb->fDsrSensitivity) shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY; + if (lpdcb->fAbortOnError) shf.ControlHandShake |= SERIAL_ERROR_ABORT; + + if (lpdcb->fErrorChar) shf.FlowReplace |= SERIAL_ERROR_CHAR; + if (lpdcb->fNull) shf.FlowReplace |= SERIAL_NULL_STRIPPING; + if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE; + if (lpdcb->fOutX) shf.FlowReplace |= SERIAL_AUTO_TRANSMIT; + if (lpdcb->fInX) shf.FlowReplace |= SERIAL_AUTO_RECEIVE; + + shf.XonLimit = lpdcb->XonLim; + shf.XoffLimit = lpdcb->XoffLim; + + sc.EofChar = lpdcb->EofChar; + sc.ErrorChar = lpdcb->ErrorChar; + sc.BreakChar = 0; + sc.EventChar = lpdcb->EvtChar; + sc.XonChar = lpdcb->XonChar; + sc.XoffChar = lpdcb->XoffChar; + + /* note: change DTR/RTS lines after setting the comm attributes, + * so flow control does not interfere. + */ + return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE, + &sbr, sizeof(sbr), NULL, 0, &dwBytesReturned, NULL) && + DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL, + &slc, sizeof(slc), NULL, 0, &dwBytesReturned, NULL) && + DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW, + &shf, sizeof(shf), NULL, 0, &dwBytesReturned, NULL) && + DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS, + &sc, sizeof(sc), NULL, 0, &dwBytesReturned, NULL)); +} + + +/***************************************************************************** + * GetCommState (KERNEL32.@) + * + * Fills in a device control block with information from a communications device. + * + * PARAMS + * handle [in] The communications device + * lpdcb [out] The device control block + * + * RETURNS + * + * True on success, false if the communication device handle is bad etc + * + * BUGS + * + * XonChar and XoffChar are not set. + */ +BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) +{ + SERIAL_BAUD_RATE sbr; + SERIAL_LINE_CONTROL slc; + SERIAL_HANDFLOW shf; + SERIAL_CHARS sc; + DWORD dwBytesReturned; + + TRACE("handle %p, ptr %p\n", handle, lpdcb); + + if (!lpdcb) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE, + NULL, 0, &sbr, sizeof(sbr), &dwBytesReturned, NULL) || + !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL, + NULL, 0, &slc, sizeof(slc), &dwBytesReturned, NULL) || + !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW, + NULL, 0, &shf, sizeof(shf), &dwBytesReturned, NULL) || + !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS, + NULL, 0, &sc, sizeof(sc), &dwBytesReturned, NULL)) + return FALSE; + + memset(lpdcb, 0, sizeof(*lpdcb)); + lpdcb->DCBlength = sizeof(*lpdcb); + + /* yes, they seem no never be (re)set on NT */ + lpdcb->fBinary = 1; + lpdcb->fParity = 0; + + lpdcb->BaudRate = sbr.BaudRate; + + lpdcb->StopBits = slc.StopBits; + lpdcb->Parity = slc.Parity; + lpdcb->ByteSize = slc.WordLength; + + if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1; + if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1; + switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE)) + { + case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break; + case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break; + case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break; + } + switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE)) + { + case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break; + case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break; + case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break; + case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE: + lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break; + } + if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1; + if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1; + if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1; + if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1; + if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1; + lpdcb->XonLim = shf.XonLimit; + lpdcb->XoffLim = shf.XoffLimit; + + if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1; + if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1; + + lpdcb->EofChar = sc.EofChar; + lpdcb->ErrorChar = sc.ErrorChar; + lpdcb->EvtChar = sc.EventChar; + lpdcb->XonChar = sc.XonChar; + lpdcb->XoffChar = sc.XoffChar; + + TRACE("OK\n"); + dump_dcb(lpdcb); + + return TRUE; +} + +/***************************************************************************** + * TransmitCommChar (KERNEL32.@) + * + * Transmits a single character in front of any pending characters in the + * output buffer. Usually used to send an interrupt character to a host. + * + * PARAMS + * hComm [in] The communication device in need of a command character + * chTransmit [in] The character to transmit + * + * RETURNS + * + * True if the call succeeded, false if the previous command character to the + * same device has not been sent yet the handle is bad etc. + * + */ +BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit) +{ + DWORD dwBytesReturned; + return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR, + &chTransmit, sizeof(chTransmit), NULL, 0, &dwBytesReturned, NULL); +} + + +/***************************************************************************** + * GetCommTimeouts (KERNEL32.@) + * + * Obtains the request timeout values for the communications device. + * + * PARAMS + * hComm [in] The communications device + * lptimeouts [out] The struct of request timeouts + * + * RETURNS + * + * True on success, false if communications device handle is bad + * or the target structure is null. + */ +BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts) +{ + SERIAL_TIMEOUTS st; + DWORD dwBytesReturned; + + TRACE("(%p, %p)\n", hComm, lptimeouts); + if (!lptimeouts) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS, + NULL, 0, &st, sizeof(st), &dwBytesReturned, NULL)) + return FALSE; + lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout; + lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier; + lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant; + lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier; + lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant; + return TRUE; +} + +/***************************************************************************** + * SetCommTimeouts (KERNEL32.@) + * + * Sets the timeouts used when reading and writing data to/from COMM ports. + * + * PARAMS + * hComm [in] handle of COMM device + * lptimeouts [in] pointer to COMMTIMEOUTS structure + * + * ReadIntervalTimeout + * - converted and passes to linux kernel as c_cc[VTIME] + * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant + * - used in ReadFile to calculate GetOverlappedResult's timeout + * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant + * - used in WriteFile to calculate GetOverlappedResult's timeout + * + * RETURNS + * + * True if the timeouts were set, false otherwise. + */ +BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts) +{ + SERIAL_TIMEOUTS st; + DWORD dwBytesReturned; + + TRACE("(%p, %p)\n", hComm, lptimeouts); + + if (lptimeouts == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout; + st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier; + st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant; + st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier; + st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant; + + return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS, + &st, sizeof(st), NULL, 0, &dwBytesReturned, NULL); +} + +/*********************************************************************** + * GetCommModemStatus (KERNEL32.@) + * + * Obtains the four control register bits if supported by the hardware. + * + * PARAMS + * + * hFile [in] The communications device + * lpModemStat [out] The control register bits + * + * RETURNS + * + * True if the communications handle was good and for hardware that + * control register access, false otherwise. + */ +BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat) +{ + DWORD dwBytesReturned; + return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS, + NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL); +} + +/*********************************************************************** + * WaitCommEvent (KERNEL32.@) + * + * Wait until something interesting happens on a COMM port. + * Interesting things (events) are set by calling SetCommMask before + * this function is called. + * + * RETURNS + * TRUE if successful + * FALSE if failure + * + * The set of detected events will be written to *lpdwEventMask + * ERROR_IO_PENDING will be returned the overlapped structure was passed + * + * BUGS: + * Only supports EV_RXCHAR and EV_TXEMPTY + */ +BOOL WINAPI WaitCommEvent( + HANDLE hFile, /* [in] handle of comm port to wait for */ + LPDWORD lpdwEvents, /* [out] event(s) that were detected */ + LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */ +{ + return DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, NULL, 0, + lpdwEvents, sizeof(DWORD), NULL, lpOverlapped); +} + +/*********************************************************************** + * GetCommProperties (KERNEL32.@) + * + * This function fills in a structure with the capabilities of the + * communications port driver. + * + * RETURNS + * + * TRUE on success, FALSE on failure + * If successful, the lpCommProp structure be filled in with + * properties of the comm port. + */ +BOOL WINAPI GetCommProperties( + HANDLE hFile, /* [in] handle of the comm port */ + LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */ +{ + TRACE("(%p %p)\n",hFile,lpCommProp); + if(!lpCommProp) + return FALSE; + + /* + * These values should be valid for LINUX's serial driver + * FIXME: Perhaps they deserve an #ifdef LINUX + */ + memset(lpCommProp,0,sizeof(COMMPROP)); + lpCommProp->wPacketLength = 1; + lpCommProp->wPacketVersion = 1; + lpCommProp->dwServiceMask = SP_SERIALCOMM; + lpCommProp->dwMaxTxQueue = 4096; + lpCommProp->dwMaxRxQueue = 4096; + lpCommProp->dwMaxBaud = BAUD_115200; + lpCommProp->dwProvSubType = PST_RS232; + lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS; + lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING | + SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ; + lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 | + BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 | + BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ; + lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ; + lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 | + PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE; + lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue; + lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue; + + return TRUE; +} + +/*********************************************************************** + * FIXME: + * The functionality of CommConfigDialogA, GetDefaultCommConfig and + * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL). + * This is dependent on the type of COMM port, but since it is doubtful + * anybody will get around to implementing support for fancy serial + * ports in WINE, this is hardcoded for the time being. The name of + * this DLL should be stored in and read from the system registry in + * the hive HKEY_LOCAL_MACHINE, key + * System\\CurrentControlSet\\Services\\Class\\Ports\\???? + * where ???? is the port number... that is determined by PNP + * The DLL should be loaded when the COMM port is opened, and closed + * when the COMM port is closed. - MJM 20 June 2000 + ***********************************************************************/ +static const WCHAR lpszSerialUI[] = { + 's','e','r','i','a','l','u','i','.','d','l','l',0 }; + + +/*********************************************************************** + * CommConfigDialogA (KERNEL32.@) + * + * Raises a dialog that allows the user to configure a comm port. + * Fills the COMMCONFIG struct with information specified by the user. + * This function should call a similar routine in the COMM driver... + * + * RETURNS + * + * TRUE on success, FALSE on failure + * If successful, the lpCommConfig structure will contain a new + * configuration for the comm port, as specified by the user. + * + * BUGS + * The library with the CommConfigDialog code is never unloaded. + * Perhaps this should be done when the comm port is closed? + */ +BOOL WINAPI CommConfigDialogA( + LPCSTR lpszDevice, /* [in] name of communications device */ + HWND hWnd, /* [in] parent window for the dialog */ + LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */ +{ + LPWSTR lpDeviceW = NULL; + DWORD len; + BOOL r; + + TRACE("(%s, %p, %p)\n", debugstr_a(lpszDevice), hWnd, lpCommConfig); + + if (lpszDevice) + { + len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 ); + lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len ); + } + r = CommConfigDialogW(lpDeviceW, hWnd, lpCommConfig); + HeapFree( GetProcessHeap(), 0, lpDeviceW ); + return r; +} + +/*********************************************************************** + * CommConfigDialogW (KERNEL32.@) + * + * See CommConfigDialogA. + */ +BOOL WINAPI CommConfigDialogW( + LPCWSTR lpszDevice, /* [in] name of communications device */ + HWND hWnd, /* [in] parent window for the dialog */ + LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */ +{ + DWORD (WINAPI *pCommConfigDialog)(LPCWSTR, HWND, LPCOMMCONFIG); + HMODULE hConfigModule; + DWORD res = ERROR_INVALID_PARAMETER; + + TRACE("(%s, %p, %p)\n", debugstr_w(lpszDevice), hWnd, lpCommConfig); + hConfigModule = LoadLibraryW(lpszSerialUI); + + if (hConfigModule) { + pCommConfigDialog = (void *)GetProcAddress(hConfigModule, "drvCommConfigDialogW"); + if (pCommConfigDialog) { + res = pCommConfigDialog(lpszDevice, hWnd, lpCommConfig); + } + FreeLibrary(hConfigModule); + } + + if (res) SetLastError(res); + return (res == ERROR_SUCCESS); +} + +/*********************************************************************** + * GetCommConfig (KERNEL32.@) + * + * Fill in the COMMCONFIG structure for the comm port hFile + * + * RETURNS + * + * TRUE on success, FALSE on failure + * If successful, lpCommConfig contains the comm port configuration. + * + * BUGS + * + */ +BOOL WINAPI GetCommConfig( + HANDLE hFile, /* [in] The communications device. */ + LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */ + LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure, + afterwards the number of bytes copied to the buffer or + the needed size of the buffer. */ +{ + BOOL r; + + TRACE("(%p, %p, %p) *lpdwSize: %u\n", hFile, lpCommConfig, lpdwSize, lpdwSize ? *lpdwSize : 0 ); + + if(lpCommConfig == NULL) + return FALSE; + r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */ + *lpdwSize = sizeof(COMMCONFIG); + if(r) + return FALSE; + + lpCommConfig->dwSize = sizeof(COMMCONFIG); + lpCommConfig->wVersion = 1; + lpCommConfig->wReserved = 0; + r = GetCommState(hFile,&lpCommConfig->dcb); + lpCommConfig->dwProviderSubType = PST_RS232; + lpCommConfig->dwProviderOffset = 0; + lpCommConfig->dwProviderSize = 0; + + return r; +} + +/*********************************************************************** + * SetCommConfig (KERNEL32.@) + * + * Sets the configuration of the communications device. + * + * RETURNS + * + * True on success, false if the handle was bad is not a communications device. + */ +BOOL WINAPI SetCommConfig( + HANDLE hFile, /* [in] The communications device. */ + LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */ + DWORD dwSize) /* [in] size of the lpCommConfig struct */ +{ + TRACE("(%p, %p, %u)\n", hFile, lpCommConfig, dwSize); + return SetCommState(hFile,&lpCommConfig->dcb); +} + +/*********************************************************************** + * SetDefaultCommConfigW (KERNEL32.@) + * + * Initializes the default configuration for a communication device. + * + * PARAMS + * lpszDevice [I] Name of the device targeted for configuration + * lpCommConfig [I] PTR to a buffer with the configuration for the device + * dwSize [I] Number of bytes in the buffer + * + * RETURNS + * Failure: FALSE + * Success: TRUE, and default configuration saved + * + */ +BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize) +{ + BOOL (WINAPI *lpfnSetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, DWORD); + HMODULE hConfigModule; + BOOL r = FALSE; + + TRACE("(%s, %p, %u)\n", debugstr_w(lpszDevice), lpCommConfig, dwSize); + + hConfigModule = LoadLibraryW(lpszSerialUI); + if(!hConfigModule) + return r; + + lpfnSetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW"); + if (lpfnSetDefaultCommConfig) + r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize); + + FreeLibrary(hConfigModule); + + return r; +} + + +/*********************************************************************** + * SetDefaultCommConfigA (KERNEL32.@) + * + * Initializes the default configuration for a communication device. + * + * See SetDefaultCommConfigW. + * + */ +BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize) +{ + BOOL r; + LPWSTR lpDeviceW = NULL; + DWORD len; + + TRACE("(%s, %p, %u)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize); + + if (lpszDevice) + { + len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 ); + lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len ); + } + r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize); + HeapFree( GetProcessHeap(), 0, lpDeviceW ); + return r; +} + + +/*********************************************************************** + * GetDefaultCommConfigW (KERNEL32.@) + * + * Acquires the default configuration of the specified communication device. (unicode) + * + * RETURNS + * + * True on successful reading of the default configuration, + * if the device is not found or the buffer is too small. + */ +BOOL WINAPI GetDefaultCommConfigW( + LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */ + LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */ + LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer, + afterwards the number of bytes copied to the buffer or + the needed size of the buffer. */ +{ + DWORD (WINAPI *pGetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, LPDWORD); + HMODULE hConfigModule; + DWORD res = ERROR_INVALID_PARAMETER; + + TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_w(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 ); + hConfigModule = LoadLibraryW(lpszSerialUI); + + if (hConfigModule) { + pGetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvGetDefaultCommConfigW"); + if (pGetDefaultCommConfig) { + res = pGetDefaultCommConfig(lpszName, lpCC, lpdwSize); + } + FreeLibrary(hConfigModule); + } + + if (res) SetLastError(res); + return (res == ERROR_SUCCESS); +} + +/************************************************************************** + * GetDefaultCommConfigA (KERNEL32.@) + * + * Acquires the default configuration of the specified communication device. (ascii) + * + * RETURNS + * + * True on successful reading of the default configuration, + * if the device is not found or the buffer is too small. + */ +BOOL WINAPI GetDefaultCommConfigA( + LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */ + LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */ + LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer, + afterwards the number of bytes copied to the buffer or + the needed size of the buffer. */ +{ + BOOL ret = FALSE; + UNICODE_STRING lpszNameW; + + TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_a(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 ); + if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName); + else lpszNameW.Buffer = NULL; + + ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize); + + RtlFreeUnicodeString(&lpszNameW); + return ret; +} diff --git a/dll/win32/kernel32/wine/lzexpand.c b/dll/win32/kernel32/wine/lzexpand.c new file mode 100644 index 00000000000..3936bd4a814 --- /dev/null +++ b/dll/win32/kernel32/wine/lzexpand.c @@ -0,0 +1,623 @@ +/* $Id$ + * + * LZ Decompression functions + * + * Copyright 1996 Marcus Meissner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * NOTES + * + * The LZ (Lempel Ziv) decompression was used in win16 installation programs. + * It is a simple tabledriven decompression engine, the algorithm is not + * documented as far as I know. WINE does not contain a compressor for + * this format. + * + * The implementation is complete and there have been no reports of failures + * for some time. + * + * TODO: + * + * o Check whether the return values are correct + * + */ +//#include +#define HFILE_ERROR ((HFILE)-1) + +//#include "config.h" +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "windef.h" +#include "winbase.h" +#include "lzexpand.h" + +#include "wine/unicode.h" +#include "wine/debug.h" +#include "winternl.h" +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap +#define _lread(a, b, c) (long)(_hread(a, b, (long)c)) +#define _lwrite(a, b, c) (long)(_hwrite(a, b, (long)c)) +WINE_DEFAULT_DEBUG_CHANNEL(file); + +/* The readahead length of the decompressor. Reading single bytes + * using _lread() would be SLOW. + */ +#define GETLEN 2048 + +#define LZ_MAGIC_LEN 8 +#define LZ_HEADER_LEN 14 + +/* Format of first 14 byte of LZ compressed file */ +struct lzfileheader { + BYTE magic[LZ_MAGIC_LEN]; + BYTE compressiontype; + CHAR lastchar; + DWORD reallength; +}; +static const BYTE LZMagic[LZ_MAGIC_LEN]={'S','Z','D','D',0x88,0xf0,0x27,0x33}; + +#define LZ_TABLE_SIZE 0x1000 + +struct lzstate { + HFILE realfd; /* the real filedescriptor */ + CHAR lastchar; /* the last char of the filename */ + + DWORD reallength; /* the decompressed length of the file */ + DWORD realcurrent; /* the position the decompressor currently is */ + DWORD realwanted; /* the position the user wants to read from */ + + BYTE table[LZ_TABLE_SIZE]; /* the rotating LZ table */ + UINT curtabent; /* CURrent TABle ENTry */ + + BYTE stringlen; /* length and position of current string */ + DWORD stringpos; /* from stringtable */ + + + WORD bytetype; /* bitmask within blocks */ + + BYTE *get; /* GETLEN bytes */ + DWORD getcur; /* current read */ + DWORD getlen; /* length last got */ +}; + +#define MAX_LZSTATES 16 +static struct lzstate *lzstates[MAX_LZSTATES]; + +#define LZ_MIN_HANDLE 0x400 +#define IS_LZ_HANDLE(h) (((h) >= LZ_MIN_HANDLE) && ((h) < LZ_MIN_HANDLE+MAX_LZSTATES)) +#define GET_LZ_STATE(h) (IS_LZ_HANDLE(h) ? lzstates[(h)-LZ_MIN_HANDLE] : NULL) + +/* reads one compressed byte, including buffering */ +#define GET(lzs,b) _lzget(lzs,&b) +#define GET_FLUSH(lzs) lzs->getcur=lzs->getlen; + +static int +_lzget(struct lzstate *lzs,BYTE *b) { + if (lzs->getcurgetlen) { + *b = lzs->get[lzs->getcur++]; + return 1; + } else { + int ret = _lread(lzs->realfd,lzs->get,GETLEN); + if (ret==HFILE_ERROR) + return HFILE_ERROR; + if (ret==0) + return 0; + lzs->getlen = ret; + lzs->getcur = 1; + *b = *(lzs->get); + return 1; + } +} +/* internal function, reads lzheader + * returns BADINHANDLE for non filedescriptors + * return 0 for file not compressed using LZ + * return UNKNOWNALG for unknown algorithm + * returns lzfileheader in *head + */ +static INT read_header(HFILE fd,struct lzfileheader *head) +{ + BYTE buf[LZ_HEADER_LEN]; + + if (_llseek(fd,0,SEEK_SET)==-1) + return LZERROR_BADINHANDLE; + + /* We can't directly read the lzfileheader struct due to + * structure element alignment + */ + if (_lread(fd,buf,LZ_HEADER_LEN)magic,buf,LZ_MAGIC_LEN); + memcpy(&(head->compressiontype),buf+LZ_MAGIC_LEN,1); + memcpy(&(head->lastchar),buf+LZ_MAGIC_LEN+1,1); + + /* FIXME: consider endianess on non-intel architectures */ + memcpy(&(head->reallength),buf+LZ_MAGIC_LEN+2,4); + + if (memcmp(head->magic,LZMagic,LZ_MAGIC_LEN)) + return 0; + if (head->compressiontype!='A') + return LZERROR_UNKNOWNALG; + return 1; +} + + +/*********************************************************************** + * LZStart (KERNEL32.@) + */ +INT WINAPI LZStart(void) +{ + TRACE("(void)\n"); + return 1; +} + + +/*********************************************************************** + * LZInit (KERNEL32.@) + * + * initializes internal decompression buffers, returns lzfiledescriptor. + * (return value the same as hfSrc, if hfSrc is not compressed) + * on failure, returns error code <0 + * lzfiledescriptors range from 0x400 to 0x410 (only 16 open files per process) + * + * since _llseek uses the same types as libc.lseek, we just use the macros of + * libc + */ +HFILE WINAPI LZInit( HFILE hfSrc ) +{ + + struct lzfileheader head; + struct lzstate *lzs; + int i, ret; + + TRACE("(%d)\n",hfSrc); + ret=read_header(hfSrc,&head); + if (ret<=0) { + _llseek(hfSrc,0,SEEK_SET); + return ret?ret:hfSrc; + } + for (i = 0; i < MAX_LZSTATES; i++) if (!lzstates[i]) break; + if (i == MAX_LZSTATES) return LZERROR_GLOBALLOC; + lzstates[i] = lzs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lzs) ); + if(lzs == NULL) return LZERROR_GLOBALLOC; + + lzs->realfd = hfSrc; + lzs->lastchar = head.lastchar; + lzs->reallength = head.reallength; + + lzs->get = HeapAlloc( GetProcessHeap(), 0, GETLEN ); + lzs->getlen = 0; + lzs->getcur = 0; + + if(lzs->get == NULL) { + HeapFree(GetProcessHeap(), 0, lzs); + lzstates[i] = NULL; + return LZERROR_GLOBALLOC; + } + + /* Yes, preinitialize with spaces */ + memset(lzs->table,' ',LZ_TABLE_SIZE); + /* Yes, start 16 byte from the END of the table */ + lzs->curtabent = 0xff0; + return LZ_MIN_HANDLE + i; +} + + +/*********************************************************************** + * LZDone (KERNEL32.@) + */ +void WINAPI LZDone(void) +{ + TRACE("(void)\n"); +} + + +/*********************************************************************** + * GetExpandedNameA (KERNEL32.@) + * + * gets the full filename of the compressed file 'in' by opening it + * and reading the header + * + * "file." is being translated to "file" + * "file.bl_" (with lastchar 'a') is being translated to "file.bla" + * "FILE.BL_" (with lastchar 'a') is being translated to "FILE.BLA" + */ + +INT WINAPI GetExpandedNameA( LPSTR in, LPSTR out ) +{ + struct lzfileheader head; + HFILE fd; + OFSTRUCT ofs; + INT fnislowercased,ret,len; + LPSTR s,t; + + TRACE("(%s)\n",in); + fd=OpenFile(in,&ofs,OF_READ); + if (fd==HFILE_ERROR) + return (INT)(INT16)LZERROR_BADINHANDLE; + strcpy(out,in); + ret=read_header(fd,&head); + if (ret<=0) { + /* not a LZ compressed file, so the expanded name is the same + * as the input name */ + _lclose(fd); + return 1; + } + + + /* look for directory prefix and skip it. */ + s=out; + while (NULL!=(t=strpbrk(s,"/\\:"))) + s=t+1; + + /* now mangle the basename */ + if (!*s) { + /* FIXME: hmm. shouldn't happen? */ + WARN("Specified a directory or what? (%s)\n",in); + _lclose(fd); + return 1; + } + /* see if we should use lowercase or uppercase on the last char */ + fnislowercased=1; + t=s+strlen(s)-1; + while (t>=out) { + if (!isalpha(*t)) { + t--; + continue; + } + fnislowercased=islower(*t); + break; + } + if (isalpha(head.lastchar)) { + if (fnislowercased) + head.lastchar=tolower(head.lastchar); + else + head.lastchar=toupper(head.lastchar); + } + + /* now look where to replace the last character */ + if (NULL!=(t=strchr(s,'.'))) { + if (t[1]=='\0') { + t[0]='\0'; + } else { + len=strlen(t)-1; + if (t[len]=='_') + t[len]=head.lastchar; + } + } /* else no modification necessary */ + _lclose(fd); + return 1; +} + + +/*********************************************************************** + * GetExpandedNameW (KERNEL32.@) + */ +INT WINAPI GetExpandedNameW( LPWSTR in, LPWSTR out ) +{ + INT ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, in, -1, NULL, 0, NULL, NULL ); + char *xin = HeapAlloc( GetProcessHeap(), 0, len ); + char *xout = HeapAlloc( GetProcessHeap(), 0, len+3 ); + WideCharToMultiByte( CP_ACP, 0, in, -1, xin, len, NULL, NULL ); + if ((ret = GetExpandedNameA( xin, xout )) > 0) + MultiByteToWideChar( CP_ACP, 0, xout, -1, out, strlenW(in)+4 ); + HeapFree( GetProcessHeap(), 0, xin ); + HeapFree( GetProcessHeap(), 0, xout ); + return ret; +} + + +/*********************************************************************** + * LZRead (KERNEL32.@) + */ +INT WINAPI LZRead( HFILE fd, LPSTR vbuf, INT toread ) +{ + int howmuch; + BYTE b,*buf; + struct lzstate *lzs; + + buf=(LPBYTE)vbuf; + TRACE("(%d,%p,%d)\n",fd,buf,toread); + howmuch=toread; + if (!(lzs = GET_LZ_STATE(fd))) return _lread(fd,buf,toread); + +/* The decompressor itself is in a define, cause we need it twice + * in this function. (the decompressed byte will be in b) + */ +#define DECOMPRESS_ONE_BYTE \ + if (lzs->stringlen) { \ + b = lzs->table[lzs->stringpos]; \ + lzs->stringpos = (lzs->stringpos+1)&0xFFF; \ + lzs->stringlen--; \ + } else { \ + if (!(lzs->bytetype&0x100)) { \ + if (1!=GET(lzs,b)) \ + return toread-howmuch; \ + lzs->bytetype = b|0xFF00; \ + } \ + if (lzs->bytetype & 1) { \ + if (1!=GET(lzs,b)) \ + return toread-howmuch; \ + } else { \ + BYTE b1,b2; \ + \ + if (1!=GET(lzs,b1)) \ + return toread-howmuch; \ + if (1!=GET(lzs,b2)) \ + return toread-howmuch; \ + /* Format: \ + * b1 b2 \ + * AB CD \ + * where CAB is the stringoffset in the table\ + * and D+3 is the len of the string \ + */ \ + lzs->stringpos = b1|((b2&0xf0)<<4); \ + lzs->stringlen = (b2&0xf)+2; \ + /* 3, but we use a byte already below ... */\ + b = lzs->table[lzs->stringpos];\ + lzs->stringpos = (lzs->stringpos+1)&0xFFF;\ + } \ + lzs->bytetype>>=1; \ + } \ + /* store b in table */ \ + lzs->table[lzs->curtabent++]= b; \ + lzs->curtabent &= 0xFFF; \ + lzs->realcurrent++; + + /* if someone has seeked, we have to bring the decompressor + * to that position + */ + if (lzs->realcurrent!=lzs->realwanted) { + /* if the wanted position is before the current position + * I see no easy way to unroll ... We have to restart at + * the beginning. *sigh* + */ + if (lzs->realcurrent>lzs->realwanted) { + /* flush decompressor state */ + _llseek(lzs->realfd,LZ_HEADER_LEN,SEEK_SET); + GET_FLUSH(lzs); + lzs->realcurrent= 0; + lzs->bytetype = 0; + lzs->stringlen = 0; + memset(lzs->table,' ',LZ_TABLE_SIZE); + lzs->curtabent = 0xFF0; + } + while (lzs->realcurrentrealwanted) { + DECOMPRESS_ONE_BYTE; + } + } + + while (howmuch) { + DECOMPRESS_ONE_BYTE; + lzs->realwanted++; + *buf++ = b; + howmuch--; + } + return toread; +#undef DECOMPRESS_ONE_BYTE +} + + +/*********************************************************************** + * LZSeek (KERNEL32.@) + */ +LONG WINAPI LZSeek( HFILE fd, LONG off, INT type ) +{ + struct lzstate *lzs; + LONG newwanted; + + TRACE("(%d,%d,%d)\n",fd,off,type); + /* not compressed? just use normal _llseek() */ + if (!(lzs = GET_LZ_STATE(fd))) return _llseek(fd,off,type); + newwanted = lzs->realwanted; + switch (type) { + case 1: /* SEEK_CUR */ + newwanted += off; + break; + case 2: /* SEEK_END */ + newwanted = lzs->reallength-off; + break; + default:/* SEEK_SET */ + newwanted = off; + break; + } + if (newwanted>lzs->reallength) + return LZERROR_BADVALUE; + if (newwanted<0) + return LZERROR_BADVALUE; + lzs->realwanted = newwanted; + return newwanted; +} + + +/*********************************************************************** + * LZCopy (KERNEL32.@) + * + * Copies everything from src to dest + * if src is a LZ compressed file, it will be uncompressed. + * will return the number of bytes written to dest or errors. + */ +LONG WINAPI LZCopy( HFILE src, HFILE dest ) +{ + int usedlzinit = 0, ret, wret; + LONG len; + HFILE oldsrc = src, srcfd; + FILETIME filetime; + struct lzstate *lzs; +#define BUFLEN 1000 + CHAR buf[BUFLEN]; + /* we need that weird typedef, for i can't seem to get function pointer + * casts right. (Or they probably just do not like WINAPI in general) + */ + typedef UINT (WINAPI *_readfun)(HFILE,LPVOID,UINT); + + _readfun xread; + + TRACE("(%d,%d)\n",src,dest); + if (!IS_LZ_HANDLE(src)) { + src = LZInit(src); + if ((INT)src <= 0) return 0; + if (src != oldsrc) usedlzinit=1; + } + + /* not compressed? just copy */ + if (!IS_LZ_HANDLE(src)) + xread=(_readfun)_hread; // ROSHACK + else + xread=(_readfun)LZRead; + len=0; + while (1) { + ret=xread(src,buf,BUFLEN); + if (ret<=0) { + if (ret==0) + break; + if (ret==-1) + return LZERROR_READ; + return ret; + } + len += ret; + wret = _lwrite(dest,buf,ret); + if (wret!=ret) + return LZERROR_WRITE; + } + + /* Maintain the timestamp of source file to destination file */ + srcfd = (!(lzs = GET_LZ_STATE(src))) ? src : lzs->realfd; + GetFileTime( LongToHandle(srcfd), NULL, NULL, &filetime ); + SetFileTime( LongToHandle(dest), NULL, NULL, &filetime ); + + /* close handle */ + if (usedlzinit) + LZClose(src); + return len; +#undef BUFLEN +} + +/* reverses GetExpandedPathname */ +static LPSTR LZEXPAND_MangleName( LPCSTR fn ) +{ + char *p; + char *mfn = HeapAlloc( GetProcessHeap(), 0, strlen(fn) + 3 ); /* "._" and \0 */ + if(mfn == NULL) return NULL; + strcpy( mfn, fn ); + if (!(p = strrchr( mfn, '\\' ))) p = mfn; + if ((p = strchr( p, '.' ))) + { + p++; + if (strlen(p) < 3) strcat( p, "_" ); /* append '_' */ + else p[strlen(p)-1] = '_'; /* replace last character */ + } + else strcat( mfn, "._" ); /* append "._" */ + return mfn; +} + + +/*********************************************************************** + * LZOpenFileA (KERNEL32.@) + * + * Opens a file. If not compressed, open it as a normal file. + */ +HFILE WINAPI LZOpenFileA( LPSTR fn, LPOFSTRUCT ofs, WORD mode ) +{ + HFILE fd,cfd; + + TRACE("(%s,%p,%d)\n",fn,ofs,mode); + /* 0x70 represents all OF_SHARE_* flags, ignore them for the check */ + fd=OpenFile(fn,ofs,mode); + if (fd==HFILE_ERROR) + { + LPSTR mfn = LZEXPAND_MangleName(fn); + fd = OpenFile(mfn,ofs,mode); + HeapFree( GetProcessHeap(), 0, mfn ); + } + if ((mode&~0x70)!=OF_READ) + return fd; + if (fd==HFILE_ERROR) + return HFILE_ERROR; + cfd=LZInit(fd); + if ((INT)cfd <= 0) return fd; + return cfd; +} + + +/*********************************************************************** + * LZOpenFileW (KERNEL32.@) + */ +HFILE WINAPI LZOpenFileW( LPWSTR fn, LPOFSTRUCT ofs, WORD mode ) +{ + HFILE ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, fn, -1, NULL, 0, NULL, NULL ); + LPSTR xfn = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( CP_ACP, 0, fn, -1, xfn, len, NULL, NULL ); + ret = LZOpenFileA(xfn,ofs,mode); + HeapFree( GetProcessHeap(), 0, xfn ); + return ret; +} + + +/*********************************************************************** + * LZClose (KERNEL32.@) + */ +void WINAPI LZClose( HFILE fd ) +{ + struct lzstate *lzs; + + TRACE("(%d)\n",fd); + if (!(lzs = GET_LZ_STATE(fd))) _lclose(fd); + else + { + HeapFree( GetProcessHeap(), 0, lzs->get ); + CloseHandle( LongToHandle(lzs->realfd) ); + lzstates[fd - LZ_MIN_HANDLE] = NULL; + HeapFree( GetProcessHeap(), 0, lzs ); + } +} + +/* + * @implemented + */ +VOID +WINAPI +LZCloseFile(IN HFILE FileHandle) +{ + /* One function uses _lclose, the other CloseHandle -- same thing */ + LZClose(FileHandle); +} + +/* + * @unimplemented + */ +ULONG +WINAPI +LZCreateFileW(IN LPCWSTR FileName, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN DWORD dwCreationDisposition, + IN LPWSTR lpString1) +{ + WARN(" LZCreateFileW Not implemented!\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + diff --git a/dll/win32/kernel32/wine/muldiv.c b/dll/win32/kernel32/wine/muldiv.c new file mode 100644 index 00000000000..f1147467a55 --- /dev/null +++ b/dll/win32/kernel32/wine/muldiv.c @@ -0,0 +1,63 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/muldiv.c + * PURPOSE: + * PROGRAMMER: Casper S. Hornstrup + * Gunnar Andre Dalsnes + * UPDATE HISTORY: + * Created 06/12/2002 + */ + +#include + + +/*********************************************************************** + * MulDiv (KERNEL32.@) + * RETURNS + * Result of multiplication and division + * -1: Overflow occurred or Divisor was 0 + * FIXME! move to correct file + * + * @implemented + */ +INT +WINAPI +MulDiv(INT nNumber, + INT nNumerator, + INT nDenominator) +{ + LARGE_INTEGER Result; + LONG Negative; + + /* Find out if this will be a negative result */ + Negative = nNumber ^ nNumerator ^ nDenominator; + + /* Turn all the parameters into absolute values */ + if (nNumber < 0) nNumber *= -1; + if (nNumerator < 0) nNumerator *= -1; + if (nDenominator < 0) nDenominator *= -1; + + /* Calculate the result */ + Result.QuadPart = Int32x32To64(nNumber, nNumerator) + (nDenominator / 2); + + /* Now check for overflow */ + if (nDenominator > Result.HighPart) + { + /* Divide the product to get the quotient and remainder */ + Result.LowPart = RtlEnlargedUnsignedDivide(*(PULARGE_INTEGER)&Result, + (ULONG)nDenominator, + (PULONG)&Result.HighPart); + + /* Do the sign changes */ + if ((LONG)Result.LowPart >= 0) + { + return (Negative >= 0) ? (LONG)Result.LowPart : -(LONG)Result.LowPart; + } + } + + /* Return overflow */ + return - 1; +} + diff --git a/dll/win32/kernel32/wine/profile.c b/dll/win32/kernel32/wine/profile.c new file mode 100644 index 00000000000..7e2981b18d2 --- /dev/null +++ b/dll/win32/kernel32/wine/profile.c @@ -0,0 +1,1804 @@ +/* + * Profile functions + * + * Copyright 1993 Miguel de Icaza + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//#include "config.h" +//#include "wine/port.h" + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winerror.h" +#include "winternl.h" +#include "wine/unicode.h" +#include "wine/library.h" +#include "wine/debug.h" + +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap +WINE_DEFAULT_DEBUG_CHANNEL(profile); + +static const char bom_utf8[] = {0xEF,0xBB,0xBF}; + +typedef enum +{ + ENCODING_ANSI = 1, + ENCODING_UTF8, + ENCODING_UTF16LE, + ENCODING_UTF16BE +} ENCODING; + +typedef struct tagPROFILEKEY +{ + WCHAR *value; + struct tagPROFILEKEY *next; + WCHAR name[1]; +} PROFILEKEY; + +typedef struct tagPROFILESECTION +{ + struct tagPROFILEKEY *key; + struct tagPROFILESECTION *next; + WCHAR name[1]; +} PROFILESECTION; + + +typedef struct +{ + BOOL changed; + PROFILESECTION *section; + WCHAR *filename; + FILETIME LastWriteTime; + ENCODING encoding; +} PROFILE; + + +#define N_CACHED_PROFILES 10 + +/* Cached profile files */ +static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL}; + +#define CurProfile (MRUProfile[0]) + +/* Check for comments in profile */ +#define IS_ENTRY_COMMENT(str) ((str)[0] == ';') + +static const WCHAR emptystringW[] = {0}; +static const WCHAR wininiW[] = { 'w','i','n','.','i','n','i',0 }; + +static RTL_CRITICAL_SECTION PROFILE_CritSect; +static RTL_CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &PROFILE_CritSect, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, 0 +}; +static RTL_CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; + +static const char hex[16] = "0123456789ABCDEF"; + +/*********************************************************************** + * PROFILE_CopyEntry + * + * Copy the content of an entry into a buffer, removing quotes, and possibly + * translating environment variables. + */ +static void PROFILE_CopyEntry( LPWSTR buffer, LPCWSTR value, int len, + BOOL strip_quote ) +{ + WCHAR quote = '\0'; + + if(!buffer) return; + + if (strip_quote && ((*value == '\'') || (*value == '\"'))) + { + if (value[1] && (value[strlenW(value)-1] == *value)) quote = *value++; + } + + lstrcpynW( buffer, value, len ); + if (quote && (len >= lstrlenW(value))) buffer[strlenW(buffer)-1] = '\0'; +} + +/* byte-swaps shorts in-place in a buffer. len is in WCHARs */ +static inline void PROFILE_ByteSwapShortBuffer(WCHAR * buffer, int len) +{ + int i; + USHORT * shortbuffer = buffer; + for (i = 0; i < len; i++) + shortbuffer[i] = RtlUshortByteSwap(shortbuffer[i]); +} + +/* writes any necessary encoding marker to the file */ +static inline void PROFILE_WriteMarker(HANDLE hFile, ENCODING encoding) +{ + DWORD dwBytesWritten; + WCHAR bom; + switch (encoding) + { + case ENCODING_ANSI: + break; + case ENCODING_UTF8: + WriteFile(hFile, bom_utf8, sizeof(bom_utf8), &dwBytesWritten, NULL); + break; + case ENCODING_UTF16LE: + bom = 0xFEFF; + WriteFile(hFile, &bom, sizeof(bom), &dwBytesWritten, NULL); + break; + case ENCODING_UTF16BE: + bom = 0xFFFE; + WriteFile(hFile, &bom, sizeof(bom), &dwBytesWritten, NULL); + break; + } +} + +static void PROFILE_WriteLine( HANDLE hFile, WCHAR * szLine, int len, ENCODING encoding) +{ + char * write_buffer; + int write_buffer_len; + DWORD dwBytesWritten; + + TRACE("writing: %s\n", debugstr_wn(szLine, len)); + + switch (encoding) + { + case ENCODING_ANSI: + write_buffer_len = WideCharToMultiByte(CP_ACP, 0, szLine, len, NULL, 0, NULL, NULL); + write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len); + if (!write_buffer) return; + len = WideCharToMultiByte(CP_ACP, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL); + WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL); + HeapFree(GetProcessHeap(), 0, write_buffer); + break; + case ENCODING_UTF8: + write_buffer_len = WideCharToMultiByte(CP_UTF8, 0, szLine, len, NULL, 0, NULL, NULL); + write_buffer = HeapAlloc(GetProcessHeap(), 0, write_buffer_len); + if (!write_buffer) return; + len = WideCharToMultiByte(CP_UTF8, 0, szLine, len, write_buffer, write_buffer_len, NULL, NULL); + WriteFile(hFile, write_buffer, len, &dwBytesWritten, NULL); + HeapFree(GetProcessHeap(), 0, write_buffer); + break; + case ENCODING_UTF16LE: + WriteFile(hFile, szLine, len * sizeof(WCHAR), &dwBytesWritten, NULL); + break; + case ENCODING_UTF16BE: + PROFILE_ByteSwapShortBuffer(szLine, len); + WriteFile(hFile, szLine, len * sizeof(WCHAR), &dwBytesWritten, NULL); + break; + default: + FIXME("encoding type %d not implemented\n", encoding); + } +} + +/*********************************************************************** + * PROFILE_Save + * + * Save a profile tree to a file. + */ +static void PROFILE_Save( HANDLE hFile, const PROFILESECTION *section, ENCODING encoding ) +{ + PROFILEKEY *key; + WCHAR *buffer, *p; + + PROFILE_WriteMarker(hFile, encoding); + + for ( ; section; section = section->next) + { + int len = 0; + + if (section->name[0]) len += strlenW(section->name) + 4; + + for (key = section->key; key; key = key->next) + { + len += strlenW(key->name) + 2; + if (key->value) len += strlenW(key->value) + 1; + } + + buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!buffer) return; + + p = buffer; + if (section->name[0]) + { + *p++ = '['; + strcpyW( p, section->name ); + p += strlenW(p); + *p++ = ']'; + *p++ = '\r'; + *p++ = '\n'; + } + + for (key = section->key; key; key = key->next) + { + strcpyW( p, key->name ); + p += strlenW(p); + if (key->value) + { + *p++ = '='; + strcpyW( p, key->value ); + p += strlenW(p); + } + *p++ = '\r'; + *p++ = '\n'; + } + PROFILE_WriteLine( hFile, buffer, len, encoding ); + HeapFree(GetProcessHeap(), 0, buffer); + } +} + + +/*********************************************************************** + * PROFILE_Free + * + * Free a profile tree. + */ +static void PROFILE_Free( PROFILESECTION *section ) +{ + PROFILESECTION *next_section; + PROFILEKEY *key, *next_key; + + for ( ; section; section = next_section) + { + for (key = section->key; key; key = next_key) + { + next_key = key->next; + HeapFree( GetProcessHeap(), 0, key->value ); + HeapFree( GetProcessHeap(), 0, key ); + } + next_section = section->next; + HeapFree( GetProcessHeap(), 0, section ); + } +} + +/* returns 1 if a character white space else 0 */ +static inline int PROFILE_isspaceW(WCHAR c) +{ + /* ^Z (DOS EOF) is a space too (found on CD-ROMs) */ + return isspaceW(c) || c == 0x1a; +} + +static inline ENCODING PROFILE_DetectTextEncoding(const void * buffer, int * len) +{ + int flags = IS_TEXT_UNICODE_SIGNATURE | + IS_TEXT_UNICODE_REVERSE_SIGNATURE | + IS_TEXT_UNICODE_ODD_LENGTH; + if (*len >= sizeof(bom_utf8) && !memcmp(buffer, bom_utf8, sizeof(bom_utf8))) + { + *len = sizeof(bom_utf8); + return ENCODING_UTF8; + } + RtlIsTextUnicode(buffer, *len, &flags); + if (flags & IS_TEXT_UNICODE_SIGNATURE) + { + *len = sizeof(WCHAR); + return ENCODING_UTF16LE; + } + if (flags & IS_TEXT_UNICODE_REVERSE_SIGNATURE) + { + *len = sizeof(WCHAR); + return ENCODING_UTF16BE; + } + *len = 0; + return ENCODING_ANSI; +} + + +/*********************************************************************** + * PROFILE_Load + * + * Load a profile tree from a file. + */ +static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding) +{ + void *buffer_base, *pBuffer; + WCHAR * szFile; + const WCHAR *szLineStart, *szLineEnd; + const WCHAR *szValueStart, *szEnd, *next_line; + int line = 0, len; + PROFILESECTION *section, *first_section; + PROFILESECTION **next_section; + PROFILEKEY *key, *prev_key, **next_key; + DWORD dwFileSize; + + TRACE("%p\n", hFile); + + dwFileSize = GetFileSize(hFile, NULL); + if (dwFileSize == INVALID_FILE_SIZE || dwFileSize == 0) + return NULL; + + buffer_base = HeapAlloc(GetProcessHeap(), 0 , dwFileSize); + if (!buffer_base) return NULL; + + if (!ReadFile(hFile, buffer_base, dwFileSize, &dwFileSize, NULL)) + { + HeapFree(GetProcessHeap(), 0, buffer_base); + WARN("Error %d reading file\n", GetLastError()); + return NULL; + } + len = dwFileSize; + *pEncoding = PROFILE_DetectTextEncoding(buffer_base, &len); + /* len is set to the number of bytes in the character marker. + * we want to skip these bytes */ + pBuffer = (char *)buffer_base + len; + dwFileSize -= len; + switch (*pEncoding) + { + case ENCODING_ANSI: + TRACE("ANSI encoding\n"); + + len = MultiByteToWideChar(CP_ACP, 0, pBuffer, dwFileSize, NULL, 0); + szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!szFile) + { + HeapFree(GetProcessHeap(), 0, buffer_base); + return NULL; + } + MultiByteToWideChar(CP_ACP, 0, pBuffer, dwFileSize, szFile, len); + szEnd = szFile + len; + break; + case ENCODING_UTF8: + TRACE("UTF8 encoding\n"); + + len = MultiByteToWideChar(CP_UTF8, 0, pBuffer, dwFileSize, NULL, 0); + szFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!szFile) + { + HeapFree(GetProcessHeap(), 0, buffer_base); + return NULL; + } + MultiByteToWideChar(CP_UTF8, 0, pBuffer, dwFileSize, szFile, len); + szEnd = szFile + len; + break; + case ENCODING_UTF16LE: + TRACE("UTF16 Little Endian encoding\n"); + szFile = pBuffer; + szEnd = (WCHAR *)((char *)pBuffer + dwFileSize); + break; + case ENCODING_UTF16BE: + TRACE("UTF16 Big Endian encoding\n"); + szFile = pBuffer; + szEnd = (WCHAR *)((char *)pBuffer + dwFileSize); + PROFILE_ByteSwapShortBuffer(szFile, dwFileSize / sizeof(WCHAR)); + break; + default: + FIXME("encoding type %d not implemented\n", *pEncoding); + HeapFree(GetProcessHeap(), 0, buffer_base); + return NULL; + } + + first_section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) ); + if(first_section == NULL) + { + if (szFile != pBuffer) + HeapFree(GetProcessHeap(), 0, szFile); + HeapFree(GetProcessHeap(), 0, buffer_base); + return NULL; + } + first_section->name[0] = 0; + first_section->key = NULL; + first_section->next = NULL; + next_section = &first_section->next; + next_key = &first_section->key; + prev_key = NULL; + next_line = szFile; + + while (next_line < szEnd) + { + szLineStart = next_line; + next_line = memchrW(szLineStart, '\n', szEnd - szLineStart); + if (!next_line) next_line = memchrW(szLineStart, '\r', szEnd - szLineStart); + if (!next_line) next_line = szEnd; + else next_line++; + szLineEnd = next_line; + + line++; + + /* get rid of white space */ + while (szLineStart < szLineEnd && PROFILE_isspaceW(*szLineStart)) szLineStart++; + while ((szLineEnd > szLineStart) && PROFILE_isspaceW(szLineEnd[-1])) szLineEnd--; + + if (szLineStart >= szLineEnd) continue; + + if (*szLineStart == '[') /* section start */ + { + const WCHAR * szSectionEnd; + if (!(szSectionEnd = memrchrW( szLineStart, ']', szLineEnd - szLineStart ))) + { + WARN("Invalid section header at line %d: %s\n", + line, debugstr_wn(szLineStart, (int)(szLineEnd - szLineStart)) ); + } + else + { + szLineStart++; + len = (int)(szSectionEnd - szLineStart); + /* no need to allocate +1 for NULL terminating character as + * already included in structure */ + if (!(section = HeapAlloc( GetProcessHeap(), 0, sizeof(*section) + len * sizeof(WCHAR) ))) + break; + memcpy(section->name, szLineStart, len * sizeof(WCHAR)); + section->name[len] = '\0'; + section->key = NULL; + section->next = NULL; + *next_section = section; + next_section = §ion->next; + next_key = §ion->key; + prev_key = NULL; + + TRACE("New section: %s\n", debugstr_w(section->name)); + + continue; + } + } + + /* get rid of white space after the name and before the start + * of the value */ + len = szLineEnd - szLineStart; + if ((szValueStart = memchrW( szLineStart, '=', szLineEnd - szLineStart )) != NULL) + { + const WCHAR *szNameEnd = szValueStart; + while ((szNameEnd > szLineStart) && PROFILE_isspaceW(szNameEnd[-1])) szNameEnd--; + len = szNameEnd - szLineStart; + szValueStart++; + while (szValueStart < szLineEnd && PROFILE_isspaceW(*szValueStart)) szValueStart++; + } + + if (len || !prev_key || *prev_key->name) + { + /* no need to allocate +1 for NULL terminating character as + * already included in structure */ + if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) + len * sizeof(WCHAR) ))) break; + memcpy(key->name, szLineStart, len * sizeof(WCHAR)); + key->name[len] = '\0'; + if (szValueStart) + { + len = (int)(szLineEnd - szValueStart); + key->value = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ); + memcpy(key->value, szValueStart, len * sizeof(WCHAR)); + key->value[len] = '\0'; + } + else key->value = NULL; + + key->next = NULL; + *next_key = key; + next_key = &key->next; + prev_key = key; + + TRACE("New key: name=%s, value=%s\n", + debugstr_w(key->name), key->value ? debugstr_w(key->value) : "(none)"); + } + } + if (szFile != pBuffer) + HeapFree(GetProcessHeap(), 0, szFile); + HeapFree(GetProcessHeap(), 0, buffer_base); + return first_section; +} + + +/*********************************************************************** + * PROFILE_DeleteSection + * + * Delete a section from a profile tree. + */ +static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCWSTR name ) +{ + while (*section) + { + if ((*section)->name[0] && !strcmpiW( (*section)->name, name )) + { + PROFILESECTION *to_del = *section; + *section = to_del->next; + to_del->next = NULL; + PROFILE_Free( to_del ); + return TRUE; + } + section = &(*section)->next; + } + return FALSE; +} + + +/*********************************************************************** + * PROFILE_DeleteKey + * + * Delete a key from a profile tree. + */ +static BOOL PROFILE_DeleteKey( PROFILESECTION **section, + LPCWSTR section_name, LPCWSTR key_name ) +{ + while (*section) + { + if ((*section)->name[0] && !strcmpiW( (*section)->name, section_name )) + { + PROFILEKEY **key = &(*section)->key; + while (*key) + { + if (!strcmpiW( (*key)->name, key_name )) + { + PROFILEKEY *to_del = *key; + *key = to_del->next; + HeapFree( GetProcessHeap(), 0, to_del->value); + HeapFree( GetProcessHeap(), 0, to_del ); + return TRUE; + } + key = &(*key)->next; + } + } + section = &(*section)->next; + } + return FALSE; +} + + +/*********************************************************************** + * PROFILE_DeleteAllKeys + * + * Delete all keys from a profile tree. + */ +static void PROFILE_DeleteAllKeys( LPCWSTR section_name) +{ + PROFILESECTION **section= &CurProfile->section; + while (*section) + { + if ((*section)->name[0] && !strcmpiW( (*section)->name, section_name )) + { + PROFILEKEY **key = &(*section)->key; + while (*key) + { + PROFILEKEY *to_del = *key; + *key = to_del->next; + HeapFree( GetProcessHeap(), 0, to_del->value); + HeapFree( GetProcessHeap(), 0, to_del ); + CurProfile->changed =TRUE; + } + } + section = &(*section)->next; + } +} + + +/*********************************************************************** + * PROFILE_Find + * + * Find a key in a profile tree, optionally creating it. + */ +static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, LPCWSTR section_name, + LPCWSTR key_name, BOOL create, BOOL create_always ) +{ + LPCWSTR p; + int seclen, keylen; + + while (PROFILE_isspaceW(*section_name)) section_name++; + if (*section_name) + p = section_name + strlenW(section_name) - 1; + else + p = section_name; + + while ((p > section_name) && PROFILE_isspaceW(*p)) p--; + seclen = p - section_name + 1; + + while (PROFILE_isspaceW(*key_name)) key_name++; + if (*key_name) + p = key_name + strlenW(key_name) - 1; + else + p = key_name; + + while ((p > key_name) && PROFILE_isspaceW(*p)) p--; + keylen = p - key_name + 1; + + while (*section) + { + if ( ((*section)->name[0]) + && (!(strncmpiW( (*section)->name, section_name, seclen ))) + && (((*section)->name)[seclen] == '\0') ) + { + PROFILEKEY **key = &(*section)->key; + + while (*key) + { + /* If create_always is FALSE then we check if the keyname + * already exists. Otherwise we add it regardless of its + * existence, to allow keys to be added more than once in + * some cases. + */ + if(!create_always) + { + if ( (!(strncmpiW( (*key)->name, key_name, keylen ))) + && (((*key)->name)[keylen] == '\0') ) + return *key; + } + key = &(*key)->next; + } + if (!create) return NULL; + if (!(*key = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILEKEY) + strlenW(key_name) * sizeof(WCHAR) ))) + return NULL; + strcpyW( (*key)->name, key_name ); + (*key)->value = NULL; + (*key)->next = NULL; + return *key; + } + section = &(*section)->next; + } + if (!create) return NULL; + *section = HeapAlloc( GetProcessHeap(), 0, sizeof(PROFILESECTION) + strlenW(section_name) * sizeof(WCHAR) ); + if(*section == NULL) return NULL; + strcpyW( (*section)->name, section_name ); + (*section)->next = NULL; + if (!((*section)->key = HeapAlloc( GetProcessHeap(), 0, + sizeof(PROFILEKEY) + strlenW(key_name) * sizeof(WCHAR) ))) + { + HeapFree(GetProcessHeap(), 0, *section); + return NULL; + } + strcpyW( (*section)->key->name, key_name ); + (*section)->key->value = NULL; + (*section)->key->next = NULL; + return (*section)->key; +} + + +/*********************************************************************** + * PROFILE_FlushFile + * + * Flush the current profile to disk if changed. + */ +static BOOL PROFILE_FlushFile(void) +{ + HANDLE hFile = NULL; + FILETIME LastWriteTime; + + if(!CurProfile) + { + WARN("No current profile!\n"); + return FALSE; + } + + if (!CurProfile->changed) return TRUE; + + hFile = CreateFileW(CurProfile->filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + WARN("could not save profile file %s (error was %d)\n", debugstr_w(CurProfile->filename), GetLastError()); + return FALSE; + } + + TRACE("Saving %s\n", debugstr_w(CurProfile->filename)); + PROFILE_Save( hFile, CurProfile->section, CurProfile->encoding ); + if(GetFileTime(hFile, NULL, NULL, &LastWriteTime)) + CurProfile->LastWriteTime=LastWriteTime; + CloseHandle( hFile ); + CurProfile->changed = FALSE; + return TRUE; +} + + +/*********************************************************************** + * PROFILE_ReleaseFile + * + * Flush the current profile to disk and remove it from the cache. + */ +static void PROFILE_ReleaseFile(void) +{ + PROFILE_FlushFile(); + PROFILE_Free( CurProfile->section ); + HeapFree( GetProcessHeap(), 0, CurProfile->filename ); + CurProfile->changed = FALSE; + CurProfile->section = NULL; + CurProfile->filename = NULL; + CurProfile->encoding = ENCODING_ANSI; + ZeroMemory(&CurProfile->LastWriteTime, sizeof(CurProfile->LastWriteTime)); +} + +/*********************************************************************** + * + * Compares a file time with the current time. If the file time is + * at least 2.1 seconds in the past, return true. + * + * Intended as cache safety measure: The time resolution on FAT is + * two seconds, so files that are not at least two seconds old might + * keep their time even on modification, so don't cache them. + */ +static BOOL is_not_current(FILETIME * ft) +{ + FILETIME Now; + LONGLONG ftll, nowll; + GetSystemTimeAsFileTime(&Now); + ftll = ((LONGLONG)ft->dwHighDateTime << 32) + ft->dwLowDateTime; + nowll = ((LONGLONG)Now.dwHighDateTime << 32) + Now.dwLowDateTime; + TRACE("%08x;%08x\n",(unsigned)ftll+21000000,(unsigned)nowll); + return ftll + 21000000 < nowll; +} + +/*********************************************************************** + * PROFILE_Open + * + * Open a profile file, checking the cached file first. + */ +static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access ) +{ + WCHAR buffer[MAX_PATH]; + HANDLE hFile = INVALID_HANDLE_VALUE; + FILETIME LastWriteTime; + int i,j; + PROFILE *tempProfile; + + ZeroMemory(&LastWriteTime, sizeof(LastWriteTime)); + + /* First time around */ + + if(!CurProfile) + for(i=0;ichanged=FALSE; + MRUProfile[i]->section=NULL; + MRUProfile[i]->filename=NULL; + MRUProfile[i]->encoding=ENCODING_ANSI; + ZeroMemory(&MRUProfile[i]->LastWriteTime, sizeof(FILETIME)); + } + + if (!filename) + filename = wininiW; + + if ((RtlDetermineDosPathNameType_U(filename) == RELATIVE_PATH) && + !strchrW(filename, '\\') && !strchrW(filename, '/')) + { + static const WCHAR wszSeparator[] = {'\\', 0}; + WCHAR windirW[MAX_PATH]; + GetWindowsDirectoryW( windirW, MAX_PATH ); + strcpyW(buffer, windirW); + strcatW(buffer, wszSeparator); + strcatW(buffer, filename); + } + else + { + LPWSTR dummy; + GetFullPathNameW(filename, sizeof(buffer)/sizeof(buffer[0]), buffer, &dummy); + } + + TRACE("path: %s\n", debugstr_w(buffer)); + + hFile = CreateFileW(buffer, GENERIC_READ | (write_access ? GENERIC_WRITE : 0), + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if ((hFile == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_FILE_NOT_FOUND)) + { + WARN("Error %d opening file %s\n", GetLastError(), debugstr_w(buffer)); + return FALSE; + } + + for(i=0;ifilename && !strcmpiW( buffer, MRUProfile[i]->filename ))) + { + TRACE("MRU Filename: %s, new filename: %s\n", debugstr_w(MRUProfile[i]->filename), debugstr_w(buffer)); + if(i) + { + PROFILE_FlushFile(); + tempProfile=MRUProfile[i]; + for(j=i;j>0;j--) + MRUProfile[j]=MRUProfile[j-1]; + CurProfile=tempProfile; + } + + if (hFile != INVALID_HANDLE_VALUE) + { + GetFileTime(hFile, NULL, NULL, &LastWriteTime); + if (!memcmp( &CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME) ) && + is_not_current(&LastWriteTime)) + TRACE("(%s): already opened (mru=%d)\n", + debugstr_w(buffer), i); + else + { + TRACE("(%s): already opened, needs refreshing (mru=%d)\n", + debugstr_w(buffer), i); + PROFILE_Free(CurProfile->section); + CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding); + CurProfile->LastWriteTime = LastWriteTime; + } + CloseHandle(hFile); + } + else TRACE("(%s): already opened, not yet created (mru=%d)\n", + debugstr_w(buffer), i); + return TRUE; + } + } + + /* Flush the old current profile */ + PROFILE_FlushFile(); + + /* Make the oldest profile the current one only in order to get rid of it */ + if(i==N_CACHED_PROFILES) + { + tempProfile=MRUProfile[N_CACHED_PROFILES-1]; + for(i=N_CACHED_PROFILES-1;i>0;i--) + MRUProfile[i]=MRUProfile[i-1]; + CurProfile=tempProfile; + } + if(CurProfile->filename) PROFILE_ReleaseFile(); + + /* OK, now that CurProfile is definitely free we assign it our new file */ + CurProfile->filename = HeapAlloc( GetProcessHeap(), 0, (strlenW(buffer)+1) * sizeof(WCHAR) ); + strcpyW( CurProfile->filename, buffer ); + + if (hFile != INVALID_HANDLE_VALUE) + { + CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding); + GetFileTime(hFile, NULL, NULL, &CurProfile->LastWriteTime); + CloseHandle(hFile); + } + else + { + /* Does not exist yet, we will create it in PROFILE_FlushFile */ + WARN("profile file %s not found\n", debugstr_w(buffer) ); + } + return TRUE; +} + + +/*********************************************************************** + * PROFILE_GetSection + * + * Returns all keys of a section. + * If return_values is TRUE, also include the corresponding values. + */ +static INT PROFILE_GetSection( PROFILESECTION *section, LPCWSTR section_name, + LPWSTR buffer, DWORD len, BOOL return_values ) +{ + PROFILEKEY *key; + + if(!buffer) return 0; + + TRACE("%s,%p,%u\n", debugstr_w(section_name), buffer, len); + + while (section) + { + if (section->name[0] && !strcmpiW( section->name, section_name )) + { + UINT oldlen = len; + for (key = section->key; key; key = key->next) + { + if (len <= 2) break; + if (!*key->name) continue; /* Skip empty lines */ + if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */ + if (!return_values && !key->value) continue; /* Skip lines w.o. '=' */ + PROFILE_CopyEntry( buffer, key->name, len - 1, 0 ); + len -= strlenW(buffer) + 1; + buffer += strlenW(buffer) + 1; + if (len < 2) + break; + if (return_values && key->value) { + buffer[-1] = '='; + PROFILE_CopyEntry ( buffer, key->value, len - 1, 0 ); + len -= strlenW(buffer) + 1; + buffer += strlenW(buffer) + 1; + } + } + *buffer = '\0'; + if (len <= 1) + /*If either lpszSection or lpszKey is NULL and the supplied + destination buffer is too small to hold all the strings, + the last string is truncated and followed by two null characters. + In this case, the return value is equal to cchReturnBuffer + minus two. */ + { + buffer[-1] = '\0'; + return oldlen - 2; + } + return oldlen - len; + } + section = section->next; + } + buffer[0] = buffer[1] = '\0'; + return 0; +} + +/* See GetPrivateProfileSectionNamesA for documentation */ +static INT PROFILE_GetSectionNames( LPWSTR buffer, DWORD len ) +{ + LPWSTR buf; + UINT buflen,tmplen; + PROFILESECTION *section; + + TRACE("(%p, %d)\n", buffer, len); + + if (!buffer || !len) + return 0; + if (len==1) { + *buffer='\0'; + return 0; + } + + buflen=len-1; + buf=buffer; + section = CurProfile->section; + while ((section!=NULL)) { + if (section->name[0]) { + tmplen = strlenW(section->name)+1; + if (tmplen >= buflen) { + if (buflen > 0) { + memcpy(buf, section->name, (buflen-1) * sizeof(WCHAR)); + buf += buflen-1; + *buf++='\0'; + } + *buf='\0'; + return len-2; + } + memcpy(buf, section->name, tmplen * sizeof(WCHAR)); + buf += tmplen; + buflen -= tmplen; + } + section = section->next; + } + *buf='\0'; + return buf-buffer; +} + + +/*********************************************************************** + * PROFILE_GetString + * + * Get a profile string. + * + * Tests with GetPrivateProfileString16, W95a, + * with filled buffer ("****...") and section "set1" and key_name "1" valid: + * section key_name def_val res buffer + * "set1" "1" "x" 43 [data] + * "set1" "1 " "x" 43 [data] (!) + * "set1" " 1 "' "x" 43 [data] (!) + * "set1" "" "x" 1 "x" + * "set1" "" "x " 1 "x" (!) + * "set1" "" " x " 3 " x" (!) + * "set1" NULL "x" 6 "1\02\03\0\0" + * "set1" "" "x" 1 "x" + * NULL "1" "x" 0 "" (!) + * "" "1" "x" 1 "x" + * NULL NULL "" 0 "" + * + * + */ +static INT PROFILE_GetString( LPCWSTR section, LPCWSTR key_name, + LPCWSTR def_val, LPWSTR buffer, DWORD len ) +{ + PROFILEKEY *key = NULL; + static const WCHAR empty_strW[] = { 0 }; + + if(!buffer || !len) return 0; + + if (!def_val) def_val = empty_strW; + if (key_name) + { + if (!key_name[0]) + { + PROFILE_CopyEntry(buffer, def_val, len, TRUE); + return strlenW(buffer); + } + key = PROFILE_Find( &CurProfile->section, section, key_name, FALSE, FALSE); + PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val, + len, TRUE ); + TRACE("(%s,%s,%s): returning %s\n", + debugstr_w(section), debugstr_w(key_name), + debugstr_w(def_val), debugstr_w(buffer) ); + return strlenW( buffer ); + } + /* no "else" here ! */ + if (section && section[0]) + { + INT ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, FALSE); + if (!buffer[0]) /* no luck -> def_val */ + { + PROFILE_CopyEntry(buffer, def_val, len, TRUE); + ret = strlenW(buffer); + } + return ret; + } + buffer[0] = '\0'; + return 0; +} + + +/*********************************************************************** + * PROFILE_SetString + * + * Set a profile string. + */ +static BOOL PROFILE_SetString( LPCWSTR section_name, LPCWSTR key_name, + LPCWSTR value, BOOL create_always ) +{ + if (!key_name) /* Delete a whole section */ + { + TRACE("(%s)\n", debugstr_w(section_name)); + CurProfile->changed |= PROFILE_DeleteSection( &CurProfile->section, + section_name ); + return TRUE; /* Even if PROFILE_DeleteSection() has failed, + this is not an error on application's level.*/ + } + else if (!value) /* Delete a key */ + { + TRACE("(%s,%s)\n", debugstr_w(section_name), debugstr_w(key_name) ); + CurProfile->changed |= PROFILE_DeleteKey( &CurProfile->section, + section_name, key_name ); + return TRUE; /* same error handling as above */ + } + else /* Set the key value */ + { + PROFILEKEY *key = PROFILE_Find(&CurProfile->section, section_name, + key_name, TRUE, create_always ); + TRACE("(%s,%s,%s):\n", + debugstr_w(section_name), debugstr_w(key_name), debugstr_w(value) ); + if (!key) return FALSE; + + /* strip the leading spaces. We can safely strip \n\r and + * friends too, they should not happen here anyway. */ + while (PROFILE_isspaceW(*value)) value++; + + if (key->value) + { + if (!strcmpW( key->value, value )) + { + TRACE(" no change needed\n" ); + return TRUE; /* No change needed */ + } + TRACE(" replacing %s\n", debugstr_w(key->value) ); + HeapFree( GetProcessHeap(), 0, key->value ); + } + else TRACE(" creating key\n" ); + key->value = HeapAlloc( GetProcessHeap(), 0, (strlenW(value)+1) * sizeof(WCHAR) ); + strcpyW( key->value, value ); + CurProfile->changed = TRUE; + } + return TRUE; +} + + +/********************* API functions **********************************/ + + +/*********************************************************************** + * GetProfileIntA (KERNEL32.@) + */ +UINT WINAPI GetProfileIntA( LPCSTR section, LPCSTR entry, INT def_val ) +{ + return GetPrivateProfileIntA( section, entry, def_val, "win.ini" ); +} + +/*********************************************************************** + * GetProfileIntW (KERNEL32.@) + */ +UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val ) +{ + return GetPrivateProfileIntW( section, entry, def_val, wininiW ); +} + +/*********************************************************************** + * GetPrivateProfileStringW (KERNEL32.@) + */ +DWORD WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry, + LPCWSTR def_val, LPWSTR buffer, + DWORD len, LPCWSTR filename ) +{ + int ret; + LPWSTR defval_tmp = NULL; + + TRACE("%s,%s,%s,%p,%u,%s\n", debugstr_w(section), debugstr_w(entry), + debugstr_w(def_val), buffer, len, debugstr_w(filename)); + + /* strip any trailing ' ' of def_val. */ + if (def_val) + { + LPCWSTR p = def_val + strlenW(def_val) - 1; + + while (p > def_val && *p == ' ') + p--; + + if (p >= def_val) + { + int len = (int)(p - def_val) + 1; + + defval_tmp = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + memcpy(defval_tmp, def_val, len * sizeof(WCHAR)); + defval_tmp[len] = '\0'; + def_val = defval_tmp; + } + } + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open( filename, FALSE )) { + if (section == NULL) + ret = PROFILE_GetSectionNames(buffer, len); + else + /* PROFILE_GetString can handle the 'entry == NULL' case */ + ret = PROFILE_GetString( section, entry, def_val, buffer, len ); + } else if (buffer && def_val) { + lstrcpynW( buffer, def_val, len ); + ret = strlenW( buffer ); + } + else + ret = 0; + + RtlLeaveCriticalSection( &PROFILE_CritSect ); + + HeapFree(GetProcessHeap(), 0, defval_tmp); + + TRACE("returning %s, %d\n", debugstr_w(buffer), ret); + + return ret; +} + +/*********************************************************************** + * GetPrivateProfileStringA (KERNEL32.@) + */ +DWORD WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry, + LPCSTR def_val, LPSTR buffer, + DWORD len, LPCSTR filename ) +{ + UNICODE_STRING sectionW, entryW, def_valW, filenameW; + LPWSTR bufferW; + INT retW, ret = 0; + + bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)) : NULL; + if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); + else sectionW.Buffer = NULL; + if (entry) RtlCreateUnicodeStringFromAsciiz(&entryW, entry); + else entryW.Buffer = NULL; + if (def_val) RtlCreateUnicodeStringFromAsciiz(&def_valW, def_val); + else def_valW.Buffer = NULL; + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + retW = GetPrivateProfileStringW( sectionW.Buffer, entryW.Buffer, + def_valW.Buffer, bufferW, len, + filenameW.Buffer); + if (len && buffer) + { + if (retW) + { + ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW, buffer, len - 1, NULL, NULL); + if (!ret) + ret = len - 1; + } + buffer[ret] = 0; + } + + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&entryW); + RtlFreeUnicodeString(&def_valW); + RtlFreeUnicodeString(&filenameW); + HeapFree(GetProcessHeap(), 0, bufferW); + return ret; +} + +/*********************************************************************** + * GetProfileStringA (KERNEL32.@) + */ +DWORD WINAPI GetProfileStringA( LPCSTR section, LPCSTR entry, LPCSTR def_val, + LPSTR buffer, DWORD len ) +{ + return GetPrivateProfileStringA( section, entry, def_val, + buffer, len, "win.ini" ); +} + +/*********************************************************************** + * GetProfileStringW (KERNEL32.@) + */ +DWORD WINAPI GetProfileStringW( LPCWSTR section, LPCWSTR entry, + LPCWSTR def_val, LPWSTR buffer, DWORD len ) +{ + return GetPrivateProfileStringW( section, entry, def_val, + buffer, len, wininiW ); +} + +/*********************************************************************** + * WriteProfileStringA (KERNEL32.@) + */ +BOOL WINAPI WriteProfileStringA( LPCSTR section, LPCSTR entry, + LPCSTR string ) +{ + return WritePrivateProfileStringA( section, entry, string, "win.ini" ); +} + +/*********************************************************************** + * WriteProfileStringW (KERNEL32.@) + */ +BOOL WINAPI WriteProfileStringW( LPCWSTR section, LPCWSTR entry, + LPCWSTR string ) +{ + return WritePrivateProfileStringW( section, entry, string, wininiW ); +} + + +/*********************************************************************** + * GetPrivateProfileIntW (KERNEL32.@) + */ +UINT WINAPI GetPrivateProfileIntW( LPCWSTR section, LPCWSTR entry, + INT def_val, LPCWSTR filename ) +{ + WCHAR buffer[30]; + UNICODE_STRING bufferW; + INT len; + ULONG result; + + if (!(len = GetPrivateProfileStringW( section, entry, emptystringW, + buffer, sizeof(buffer)/sizeof(WCHAR), + filename ))) + return def_val; + + /* FIXME: if entry can be found but it's empty, then Win16 is + * supposed to return 0 instead of def_val ! Difficult/problematic + * to implement (every other failure also returns zero buffer), + * thus wait until testing framework avail for making sure nothing + * else gets broken that way. */ + if (!buffer[0]) return (UINT)def_val; + + RtlInitUnicodeString( &bufferW, buffer ); + RtlUnicodeStringToInteger( &bufferW, 0, &result); + return result; +} + +/*********************************************************************** + * GetPrivateProfileIntA (KERNEL32.@) + * + * FIXME: rewrite using unicode + */ +UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry, + INT def_val, LPCSTR filename ) +{ + UNICODE_STRING entryW, filenameW, sectionW; + UINT res; + if(entry) RtlCreateUnicodeStringFromAsciiz(&entryW, entry); + else entryW.Buffer = NULL; + if(filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + if(section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); + else sectionW.Buffer = NULL; + res = GetPrivateProfileIntW(sectionW.Buffer, entryW.Buffer, def_val, + filenameW.Buffer); + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&filenameW); + RtlFreeUnicodeString(&entryW); + return res; +} + +/*********************************************************************** + * GetPrivateProfileSectionW (KERNEL32.@) + */ +DWORD WINAPI GetPrivateProfileSectionW( LPCWSTR section, LPWSTR buffer, + DWORD len, LPCWSTR filename ) +{ + int ret = 0; + + if (!section || !buffer) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + TRACE("(%s, %p, %d, %s)\n", debugstr_w(section), buffer, len, debugstr_w(filename)); + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open( filename, FALSE )) + ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, TRUE); + + RtlLeaveCriticalSection( &PROFILE_CritSect ); + + return ret; +} + +/*********************************************************************** + * GetPrivateProfileSectionA (KERNEL32.@) + */ +DWORD WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer, + DWORD len, LPCSTR filename ) +{ + UNICODE_STRING sectionW, filenameW; + LPWSTR bufferW; + INT retW, ret = 0; + + if (!section || !buffer) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + bufferW = HeapAlloc(GetProcessHeap(), 0, len * 2 * sizeof(WCHAR)); + RtlCreateUnicodeStringFromAsciiz(§ionW, section); + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + retW = GetPrivateProfileSectionW(sectionW.Buffer, bufferW, len * 2, filenameW.Buffer); + if (retW) + { + if (retW == len * 2 - 2) retW++; /* overflow */ + ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW + 1, buffer, len, NULL, NULL); + if (!ret || ret == len) /* overflow */ + { + ret = len - 2; + buffer[len-2] = 0; + buffer[len-1] = 0; + } + else ret--; + } + else + { + buffer[0] = 0; + buffer[1] = 0; + } + + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&filenameW); + HeapFree(GetProcessHeap(), 0, bufferW); + return ret; +} + +/*********************************************************************** + * GetProfileSectionA (KERNEL32.@) + */ +DWORD WINAPI GetProfileSectionA( LPCSTR section, LPSTR buffer, DWORD len ) +{ + return GetPrivateProfileSectionA( section, buffer, len, "win.ini" ); +} + +/*********************************************************************** + * GetProfileSectionW (KERNEL32.@) + */ +DWORD WINAPI GetProfileSectionW( LPCWSTR section, LPWSTR buffer, DWORD len ) +{ + return GetPrivateProfileSectionW( section, buffer, len, wininiW ); +} + + +/*********************************************************************** + * WritePrivateProfileStringW (KERNEL32.@) + */ +BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry, + LPCWSTR string, LPCWSTR filename ) +{ + BOOL ret = FALSE; + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (!section && !entry && !string) /* documented "file flush" case */ + { + if (!filename || PROFILE_Open( filename, TRUE )) + { + if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ + } + } + else if (PROFILE_Open( filename, TRUE )) + { + if (!section) { + SetLastError(ERROR_FILE_NOT_FOUND); + } else { + ret = PROFILE_SetString( section, entry, string, FALSE); + PROFILE_FlushFile(); + } + } + + RtlLeaveCriticalSection( &PROFILE_CritSect ); + return ret; +} + +/*********************************************************************** + * WritePrivateProfileStringA (KERNEL32.@) + */ +BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry, + LPCSTR string, LPCSTR filename ) +{ + UNICODE_STRING sectionW, entryW, stringW, filenameW; + BOOL ret; + + if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); + else sectionW.Buffer = NULL; + if (entry) RtlCreateUnicodeStringFromAsciiz(&entryW, entry); + else entryW.Buffer = NULL; + if (string) RtlCreateUnicodeStringFromAsciiz(&stringW, string); + else stringW.Buffer = NULL; + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + ret = WritePrivateProfileStringW(sectionW.Buffer, entryW.Buffer, + stringW.Buffer, filenameW.Buffer); + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&entryW); + RtlFreeUnicodeString(&stringW); + RtlFreeUnicodeString(&filenameW); + return ret; +} + +/*********************************************************************** + * WritePrivateProfileSectionW (KERNEL32.@) + */ +BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section, + LPCWSTR string, LPCWSTR filename ) +{ + BOOL ret = FALSE; + LPWSTR p; + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (!section && !string) + { + if (!filename || PROFILE_Open( filename, TRUE )) + { + if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ + } + } + else if (PROFILE_Open( filename, TRUE )) { + if (!string) {/* delete the named section*/ + ret = PROFILE_SetString(section,NULL,NULL, FALSE); + PROFILE_FlushFile(); + } else { + PROFILE_DeleteAllKeys(section); + ret = TRUE; + while(*string) { + LPWSTR buf = HeapAlloc( GetProcessHeap(), 0, (strlenW(string)+1) * sizeof(WCHAR) ); + strcpyW( buf, string ); + if((p = strchrW( buf, '='))) { + *p='\0'; + ret = PROFILE_SetString( section, buf, p+1, TRUE); + } + HeapFree( GetProcessHeap(), 0, buf ); + string += strlenW(string)+1; + } + PROFILE_FlushFile(); + } + } + + RtlLeaveCriticalSection( &PROFILE_CritSect ); + return ret; +} + +/*********************************************************************** + * WritePrivateProfileSectionA (KERNEL32.@) + */ +BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section, + LPCSTR string, LPCSTR filename) + +{ + UNICODE_STRING sectionW, filenameW; + LPWSTR stringW; + BOOL ret; + + if (string) + { + INT lenA, lenW; + LPCSTR p = string; + + while(*p) p += strlen(p) + 1; + lenA = p - string + 1; + lenW = MultiByteToWideChar(CP_ACP, 0, string, lenA, NULL, 0); + if ((stringW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR)))) + MultiByteToWideChar(CP_ACP, 0, string, lenA, stringW, lenW); + } + else stringW = NULL; + if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); + else sectionW.Buffer = NULL; + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + ret = WritePrivateProfileSectionW(sectionW.Buffer, stringW, filenameW.Buffer); + + HeapFree(GetProcessHeap(), 0, stringW); + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&filenameW); + return ret; +} + +/*********************************************************************** + * WriteProfileSectionA (KERNEL32.@) + */ +BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values) + +{ + return WritePrivateProfileSectionA( section, keys_n_values, "win.ini"); +} + +/*********************************************************************** + * WriteProfileSectionW (KERNEL32.@) + */ +BOOL WINAPI WriteProfileSectionW( LPCWSTR section, LPCWSTR keys_n_values) +{ + return WritePrivateProfileSectionW(section, keys_n_values, wininiW); +} + + +/*********************************************************************** + * GetPrivateProfileSectionNamesW (KERNEL32.@) + * + * Returns the section names contained in the specified file. + * FIXME: Where do we find this file when the path is relative? + * The section names are returned as a list of strings with an extra + * '\0' to mark the end of the list. Except for that the behavior + * depends on the Windows version. + * + * Win95: + * - if the buffer is 0 or 1 character long then it is as if it was of + * infinite length. + * - otherwise, if the buffer is too small only the section names that fit + * are returned. + * - note that this means if the buffer was too small to return even just + * the first section name then a single '\0' will be returned. + * - the return value is the number of characters written in the buffer, + * except if the buffer was too small in which case len-2 is returned + * + * Win2000: + * - if the buffer is 0, 1 or 2 characters long then it is filled with + * '\0' and the return value is 0 + * - otherwise if the buffer is too small then the first section name that + * does not fit is truncated so that the string list can be terminated + * correctly (double '\0') + * - the return value is the number of characters written in the buffer + * except for the trailing '\0'. If the buffer is too small, then the + * return value is len-2 + * - Win2000 has a bug that triggers when the section names and the + * trailing '\0' fit exactly in the buffer. In that case the trailing + * '\0' is missing. + * + * Wine implements the observed Win2000 behavior (except for the bug). + * + * Note that when the buffer is big enough then the return value may be any + * value between 1 and len-1 (or len in Win95), including len-2. + */ +DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size, + LPCWSTR filename) +{ + DWORD ret = 0; + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open( filename, FALSE )) + ret = PROFILE_GetSectionNames(buffer, size); + + RtlLeaveCriticalSection( &PROFILE_CritSect ); + + return ret; +} + + +/*********************************************************************** + * GetPrivateProfileSectionNamesA (KERNEL32.@) + */ +DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size, + LPCSTR filename) +{ + UNICODE_STRING filenameW; + LPWSTR bufferW; + INT retW, ret = 0; + + bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)) : NULL; + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + retW = GetPrivateProfileSectionNamesW(bufferW, size, filenameW.Buffer); + if (retW && size) + { + ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW+1, buffer, size-1, NULL, NULL); + if (!ret) + { + ret = size-2; + buffer[size-1] = 0; + } + else + ret = ret-1; + } + else if(size) + buffer[0] = '\0'; + + RtlFreeUnicodeString(&filenameW); + HeapFree(GetProcessHeap(), 0, bufferW); + return ret; +} + +/*********************************************************************** + * GetPrivateProfileStructW (KERNEL32.@) + * + * Should match Win95's behaviour pretty much + */ +BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key, + LPVOID buf, UINT len, LPCWSTR filename) +{ + BOOL ret = FALSE; + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open( filename, FALSE )) { + PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE, FALSE); + if (k) { + TRACE("value (at %p): %s\n", k->value, debugstr_w(k->value)); + if (((strlenW(k->value) - 2) / 2) == len) + { + LPWSTR end, p; + BOOL valid = TRUE; + WCHAR c; + DWORD chksum = 0; + + end = k->value + strlenW(k->value); /* -> '\0' */ + /* check for invalid chars in ASCII coded hex string */ + for (p=k->value; p < end; p++) + { + if (!isxdigitW(*p)) + { + WARN("invalid char '%x' in file %s->[%s]->%s !\n", + *p, debugstr_w(filename), debugstr_w(section), debugstr_w(key)); + valid = FALSE; + break; + } + } + if (valid) + { + BOOL highnibble = TRUE; + BYTE b = 0, val; + LPBYTE binbuf = buf; + + end -= 2; /* don't include checksum in output data */ + /* translate ASCII hex format into binary data */ + for (p=k->value; p < end; p++) + { + c = toupperW(*p); + val = (c > '9') ? + (c - 'A' + 10) : (c - '0'); + + if (highnibble) + b = val << 4; + else + { + b += val; + *binbuf++ = b; /* feed binary data into output */ + chksum += b; /* calculate checksum */ + } + highnibble ^= 1; /* toggle */ + } + /* retrieve stored checksum value */ + c = toupperW(*p++); + b = ( (c > '9') ? (c - 'A' + 10) : (c - '0') ) << 4; + c = toupperW(*p); + b += (c > '9') ? (c - 'A' + 10) : (c - '0'); + if (b == (chksum & 0xff)) /* checksums match ? */ + ret = TRUE; + } + } + } + } + RtlLeaveCriticalSection( &PROFILE_CritSect ); + + return ret; +} + +/*********************************************************************** + * GetPrivateProfileStructA (KERNEL32.@) + */ +BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key, + LPVOID buffer, UINT len, LPCSTR filename) +{ + UNICODE_STRING sectionW, keyW, filenameW; + INT ret; + + if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); + else sectionW.Buffer = NULL; + if (key) RtlCreateUnicodeStringFromAsciiz(&keyW, key); + else keyW.Buffer = NULL; + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + ret = GetPrivateProfileStructW(sectionW.Buffer, keyW.Buffer, buffer, len, + filenameW.Buffer); + /* Do not translate binary data. */ + + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&keyW); + RtlFreeUnicodeString(&filenameW); + return ret; +} + + + +/*********************************************************************** + * WritePrivateProfileStructW (KERNEL32.@) + */ +BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key, + LPVOID buf, UINT bufsize, LPCWSTR filename) +{ + BOOL ret = FALSE; + LPBYTE binbuf; + LPWSTR outstring, p; + DWORD sum = 0; + + if (!section && !key && !buf) /* flush the cache */ + return WritePrivateProfileStringW( NULL, NULL, NULL, filename ); + + /* allocate string buffer for hex chars + checksum hex char + '\0' */ + outstring = HeapAlloc( GetProcessHeap(), 0, (bufsize*2 + 2 + 1) * sizeof(WCHAR) ); + p = outstring; + for (binbuf = (LPBYTE)buf; binbuf < (LPBYTE)buf+bufsize; binbuf++) { + *p++ = hex[*binbuf >> 4]; + *p++ = hex[*binbuf & 0xf]; + sum += *binbuf; + } + /* checksum is sum & 0xff */ + *p++ = hex[(sum & 0xf0) >> 4]; + *p++ = hex[sum & 0xf]; + *p++ = '\0'; + + RtlEnterCriticalSection( &PROFILE_CritSect ); + + if (PROFILE_Open( filename, TRUE )) { + ret = PROFILE_SetString( section, key, outstring, FALSE); + PROFILE_FlushFile(); + } + + RtlLeaveCriticalSection( &PROFILE_CritSect ); + + HeapFree( GetProcessHeap(), 0, outstring ); + + return ret; +} + +/*********************************************************************** + * WritePrivateProfileStructA (KERNEL32.@) + */ +BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key, + LPVOID buf, UINT bufsize, LPCSTR filename) +{ + UNICODE_STRING sectionW, keyW, filenameW; + INT ret; + + if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); + else sectionW.Buffer = NULL; + if (key) RtlCreateUnicodeStringFromAsciiz(&keyW, key); + else keyW.Buffer = NULL; + if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + else filenameW.Buffer = NULL; + + /* Do not translate binary data. */ + ret = WritePrivateProfileStructW(sectionW.Buffer, keyW.Buffer, buf, bufsize, + filenameW.Buffer); + + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&keyW); + RtlFreeUnicodeString(&filenameW); + return ret; +} + + +/*********************************************************************** + * OpenProfileUserMapping (KERNEL32.@) + */ +BOOL WINAPI OpenProfileUserMapping(void) { + FIXME("(), stub!\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/*********************************************************************** + * CloseProfileUserMapping (KERNEL32.@) + */ +BOOL WINAPI CloseProfileUserMapping(void) { + FIXME("(), stub!\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} diff --git a/dll/win32/kernel32/wine/res.c b/dll/win32/kernel32/wine/res.c new file mode 100644 index 00000000000..82ed63ac9b6 --- /dev/null +++ b/dll/win32/kernel32/wine/res.c @@ -0,0 +1,1735 @@ +/* + * Resources + * + * Copyright 1993 Robert J. Amstadt + * Copyright 1995, 2003 Alexandre Julliard + * Copyright 2006 Mike McCormack + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//#include "config.h" +//#include "wine/port.h" + +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "wine/debug.h" +#include "wine/exception.h" +#include "wine/unicode.h" +#include "wine/list.h" + +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap +WINE_DEFAULT_DEBUG_CHANNEL(resource); + +/* we don't want to include winuser.h just for this */ +#define IS_INTRESOURCE(x) (((ULONG_PTR)(x) >> 16) == 0) + +/* retrieve the resource name to pass to the ntdll functions */ +static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str ) +{ + if (IS_INTRESOURCE(name)) + { + str->Buffer = ULongToPtr(LOWORD(name)); + return STATUS_SUCCESS; + } + if (name[0] == '#') + { + ULONG value; + if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value)) + return STATUS_INVALID_PARAMETER; + str->Buffer = ULongToPtr(value); + return STATUS_SUCCESS; + } + RtlCreateUnicodeStringFromAsciiz( str, name ); + RtlUpcaseUnicodeString( str, str, FALSE ); + return STATUS_SUCCESS; +} + +/* retrieve the resource name to pass to the ntdll functions */ +static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str ) +{ + if (IS_INTRESOURCE(name)) + { + str->Buffer = ULongToPtr(LOWORD(name)); + return STATUS_SUCCESS; + } + if (name[0] == '#') + { + ULONG value; + RtlInitUnicodeString( str, name + 1 ); + if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value)) + return STATUS_INVALID_PARAMETER; + str->Buffer = ULongToPtr(value); + return STATUS_SUCCESS; + } + RtlCreateUnicodeString( str, name ); + RtlUpcaseUnicodeString( str, str, FALSE ); + return STATUS_SUCCESS; +} + +/* implementation of FindResourceExA */ +static HRSRC find_resourceA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang ) +{ + NTSTATUS status; + UNICODE_STRING nameW, typeW; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL; + + nameW.Buffer = NULL; + typeW.Buffer = NULL; + + __TRY + { + if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) goto done; + if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) goto done; + info.Type = (ULONG_PTR)typeW.Buffer; + info.Name = (ULONG_PTR)nameW.Buffer; + info.Language = lang; + status = LdrFindResource_U( hModule, &info, 3, &entry ); + done: + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + } + __EXCEPT_PAGE_FAULT + { + SetLastError( ERROR_INVALID_PARAMETER ); + } + __ENDTRY + + if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); + if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + return (HRSRC)entry; +} + + +/* implementation of FindResourceExW */ +static HRSRC find_resourceW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang ) +{ + NTSTATUS status; + UNICODE_STRING nameW, typeW; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL; + + nameW.Buffer = typeW.Buffer = NULL; + + __TRY + { + if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) goto done; + if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) goto done; + info.Type = (ULONG_PTR)typeW.Buffer; + info.Name = (ULONG_PTR)nameW.Buffer; + info.Language = lang; + status = LdrFindResource_U( hModule, &info, 3, &entry ); + done: + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + } + __EXCEPT_PAGE_FAULT + { + SetLastError( ERROR_INVALID_PARAMETER ); + } + __ENDTRY + + if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); + if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + return (HRSRC)entry; +} + +/********************************************************************** + * FindResourceExA (KERNEL32.@) + */ +HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang ) +{ + TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang ); + + if (!hModule) hModule = GetModuleHandleW(0); + return find_resourceA( hModule, type, name, lang ); +} + + +/********************************************************************** + * FindResourceA (KERNEL32.@) + */ +HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type ) +{ + return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) ); +} + + +/********************************************************************** + * FindResourceExW (KERNEL32.@) + */ +HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang ) +{ + TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang ); + + if (!hModule) hModule = GetModuleHandleW(0); + return find_resourceW( hModule, type, name, lang ); +} + + +/********************************************************************** + * FindResourceW (KERNEL32.@) + */ +HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type ) +{ + return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) ); +} + + +/********************************************************************** + * EnumResourceTypesA (KERNEL32.@) + */ +BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam ) +{ + int i; + BOOL ret = FALSE; + LPSTR type = NULL; + DWORD len = 0, newlen; + NTSTATUS status; + const IMAGE_RESOURCE_DIRECTORY *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + const IMAGE_RESOURCE_DIR_STRING_U *str; + + TRACE( "%p %p %lx\n", hmod, lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleA( NULL ); + + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) + { + if (et[i].u1.s1.NameIsString) + { + str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)resdir + et[i].u1.s1.NameOffset); + newlen = WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL); + if (newlen + 1 > len) + { + len = newlen + 1; + HeapFree( GetProcessHeap(), 0, type ); + if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; + } + WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL); + type[newlen] = 0; + ret = lpfun(hmod,type,lparam); + } + else + { + ret = lpfun( hmod, UIntToPtr(et[i].u1.Id), lparam ); + } + if (!ret) break; + } + HeapFree( GetProcessHeap(), 0, type ); + return ret; +} + + +/********************************************************************** + * EnumResourceTypesW (KERNEL32.@) + */ +BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam ) +{ + int i, len = 0; + BOOL ret = FALSE; + LPWSTR type = NULL; + NTSTATUS status; + const IMAGE_RESOURCE_DIRECTORY *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + const IMAGE_RESOURCE_DIR_STRING_U *str; + + TRACE( "%p %p %lx\n", hmod, lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleW( NULL ); + + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) + { + if (et[i].u1.s1.NameIsString) + { + str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)resdir + et[i].u1.s1.NameOffset); + if (str->Length + 1 > len) + { + len = str->Length + 1; + HeapFree( GetProcessHeap(), 0, type ); + if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE; + } + memcpy(type, str->NameString, str->Length * sizeof (WCHAR)); + type[str->Length] = 0; + ret = lpfun(hmod,type,lparam); + } + else + { + ret = lpfun( hmod, UIntToPtr(et[i].u1.Id), lparam ); + } + if (!ret) break; + } + HeapFree( GetProcessHeap(), 0, type ); + return ret; +} + + +/********************************************************************** + * EnumResourceNamesA (KERNEL32.@) + */ +BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam ) +{ + int i; + BOOL ret = FALSE; + DWORD len = 0, newlen; + LPSTR name = NULL; + NTSTATUS status; + UNICODE_STRING typeW; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + const IMAGE_RESOURCE_DIR_STRING_U *str; + + TRACE( "%p %s %p %lx\n", hmod, debugstr_a(type), lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleA( NULL ); + typeW.Buffer = NULL; + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG_PTR)typeW.Buffer; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS) + goto done; + + et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + __TRY + { + for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) + { + if (et[i].u1.s1.NameIsString) + { + str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)basedir + et[i].u1.s1.NameOffset); + newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL); + if (newlen + 1 > len) + { + len = newlen + 1; + HeapFree( GetProcessHeap(), 0, name ); + if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 ))) + { + ret = FALSE; + break; + } + } + WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL ); + name[newlen] = 0; + ret = lpfun(hmod,type,name,lparam); + } + else + { + ret = lpfun( hmod, type, UIntToPtr(et[i].u1.Id), lparam ); + } + if (!ret) break; + } + } + __EXCEPT_PAGE_FAULT + { + ret = FALSE; + status = STATUS_ACCESS_VIOLATION; + } + __ENDTRY + +done: + HeapFree( GetProcessHeap(), 0, name ); + if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; +} + + +/********************************************************************** + * EnumResourceNamesW (KERNEL32.@) + */ +BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam ) +{ + int i, len = 0; + BOOL ret = FALSE; + LPWSTR name = NULL; + NTSTATUS status; + UNICODE_STRING typeW; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + const IMAGE_RESOURCE_DIR_STRING_U *str; + + TRACE( "%p %s %p %lx\n", hmod, debugstr_w(type), lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleW( NULL ); + typeW.Buffer = NULL; + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG_PTR)typeW.Buffer; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS) + goto done; + + et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + __TRY + { + for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) + { + if (et[i].u1.s1.NameIsString) + { + str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)basedir + et[i].u1.s1.NameOffset); + if (str->Length + 1 > len) + { + len = str->Length + 1; + HeapFree( GetProcessHeap(), 0, name ); + if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + { + ret = FALSE; + break; + } + } + memcpy(name, str->NameString, str->Length * sizeof (WCHAR)); + name[str->Length] = 0; + ret = lpfun(hmod,type,name,lparam); + } + else + { + ret = lpfun( hmod, type, UIntToPtr(et[i].u1.Id), lparam ); + } + if (!ret) break; + } + } + __EXCEPT_PAGE_FAULT + { + ret = FALSE; + status = STATUS_ACCESS_VIOLATION; + } + __ENDTRY +done: + HeapFree( GetProcessHeap(), 0, name ); + if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; +} + + +/********************************************************************** + * EnumResourceLanguagesA (KERNEL32.@) + */ +BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name, + ENUMRESLANGPROCA lpfun, LONG_PTR lparam ) +{ + int i; + BOOL ret = FALSE; + NTSTATUS status; + UNICODE_STRING typeW, nameW; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + + TRACE( "%p %s %s %p %lx\n", hmod, debugstr_a(type), debugstr_a(name), lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleA( NULL ); + typeW.Buffer = nameW.Buffer = NULL; + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG_PTR)typeW.Buffer; + info.Name = (ULONG_PTR)nameW.Buffer; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS) + goto done; + + et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + __TRY + { + for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) + { + ret = lpfun( hmod, type, name, et[i].u1.Id, lparam ); + if (!ret) break; + } + } + __EXCEPT_PAGE_FAULT + { + ret = FALSE; + status = STATUS_ACCESS_VIOLATION; + } + __ENDTRY +done: + if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; +} + + +/********************************************************************** + * EnumResourceLanguagesW (KERNEL32.@) + */ +BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name, + ENUMRESLANGPROCW lpfun, LONG_PTR lparam ) +{ + int i; + BOOL ret = FALSE; + NTSTATUS status; + UNICODE_STRING typeW, nameW; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + + TRACE( "%p %s %s %p %lx\n", hmod, debugstr_w(type), debugstr_w(name), lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleW( NULL ); + typeW.Buffer = nameW.Buffer = NULL; + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG_PTR)typeW.Buffer; + info.Name = (ULONG_PTR)nameW.Buffer; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS) + goto done; + + et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + __TRY + { + for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) + { + ret = lpfun( hmod, type, name, et[i].u1.Id, lparam ); + if (!ret) break; + } + } + __EXCEPT_PAGE_FAULT + { + ret = FALSE; + status = STATUS_ACCESS_VIOLATION; + } + __ENDTRY +done: + if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; +} + + +/********************************************************************** + * LoadResource (KERNEL32.@) + */ +HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc ) +{ + NTSTATUS status; + void *ret = NULL; + + TRACE( "%p %p\n", hModule, hRsrc ); + + if (!hRsrc) return 0; + if (!hModule) hModule = GetModuleHandleA( NULL ); + status = LdrAccessResource( hModule, (IMAGE_RESOURCE_DATA_ENTRY *)hRsrc, &ret, NULL ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; +} + + +/********************************************************************** + * LockResource (KERNEL32.@) + */ +LPVOID WINAPI LockResource( HGLOBAL handle ) +{ + return handle; +} + + +/********************************************************************** + * FreeResource (KERNEL32.@) + */ +BOOL WINAPI FreeResource( HGLOBAL handle ) +{ + return 0; +} + + +/********************************************************************** + * SizeofResource (KERNEL32.@) + */ +DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc ) +{ + if (!hRsrc) return 0; + return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size; +} + +/* + * Data structure for updating resources. + * Type/Name/Language is a keyset for accessing resource data. + * + * QUEUEDUPDATES (root) -> + * list of struct resource_dir_entry (Type) -> + * list of struct resource_dir_entry (Name) -> + * list of struct resource_data Language + Data + */ + +typedef struct +{ + LPWSTR pFileName; + BOOL bDeleteExistingResources; + struct list root; +} QUEUEDUPDATES; + +/* this structure is shared for types and names */ +struct resource_dir_entry { + struct list entry; + LPWSTR id; + struct list children; +}; + +/* this structure is the leaf */ +struct resource_data { + struct list entry; + LANGID lang; + DWORD codepage; + DWORD cbData; + void *lpData; +}; + +static int resource_strcmp( LPCWSTR a, LPCWSTR b ) +{ + if ( a == b ) + return 0; + if (!IS_INTRESOURCE( a ) && !IS_INTRESOURCE( b ) ) + return lstrcmpW( a, b ); + /* strings come before ids */ + if (!IS_INTRESOURCE( a ) && IS_INTRESOURCE( b )) + return -1; + if (!IS_INTRESOURCE( b ) && IS_INTRESOURCE( a )) + return 1; + return ( a < b ) ? -1 : 1; +} + +static struct resource_dir_entry *find_resource_dir_entry( struct list *dir, LPCWSTR id ) +{ + struct resource_dir_entry *ent; + + /* match either IDs or strings */ + LIST_FOR_EACH_ENTRY( ent, dir, struct resource_dir_entry, entry ) + if (!resource_strcmp( id, ent->id )) + return ent; + + return NULL; +} + +static struct resource_data *find_resource_data( struct list *dir, LANGID lang ) +{ + struct resource_data *res_data; + + /* match only languages here */ + LIST_FOR_EACH_ENTRY( res_data, dir, struct resource_data, entry ) + if ( lang == res_data->lang ) + return res_data; + + return NULL; +} + +static void add_resource_dir_entry( struct list *dir, struct resource_dir_entry *resdir ) +{ + struct resource_dir_entry *ent; + + LIST_FOR_EACH_ENTRY( ent, dir, struct resource_dir_entry, entry ) + { + if (0>resource_strcmp( ent->id, resdir->id )) + continue; + + list_add_before( &ent->entry, &resdir->entry ); + return; + } + list_add_tail( dir, &resdir->entry ); +} + +static void add_resource_data_entry( struct list *dir, struct resource_data *resdata ) +{ + struct resource_data *ent; + + LIST_FOR_EACH_ENTRY( ent, dir, struct resource_data, entry ) + { + if (ent->lang < resdata->lang) + continue; + + list_add_before( &ent->entry, &resdata->entry ); + return; + } + list_add_tail( dir, &resdata->entry ); +} + +static LPWSTR res_strdupW( LPCWSTR str ) +{ + LPWSTR ret; + UINT len; + + if (IS_INTRESOURCE(str)) + return (LPWSTR) (UINT_PTR) LOWORD(str); + len = (lstrlenW( str ) + 1) * sizeof (WCHAR); + ret = HeapAlloc( GetProcessHeap(), 0, len ); + memcpy( ret, str, len ); + return ret; +} + +static void res_free_str( LPWSTR str ) +{ + if (!IS_INTRESOURCE(str)) + HeapFree( GetProcessHeap(), 0, str ); +} + +static BOOL update_add_resource( QUEUEDUPDATES *updates, LPCWSTR Type, LPCWSTR Name, + LANGID Lang, struct resource_data *resdata, + BOOL overwrite_existing ) +{ + struct resource_dir_entry *restype, *resname; + struct resource_data *existing; + + TRACE("%p %s %s %p %d\n", updates, + debugstr_w(Type), debugstr_w(Name), resdata, overwrite_existing ); + + restype = find_resource_dir_entry( &updates->root, Type ); + if (!restype) + { + restype = HeapAlloc( GetProcessHeap(), 0, sizeof *restype ); + restype->id = res_strdupW( Type ); + list_init( &restype->children ); + add_resource_dir_entry( &updates->root, restype ); + } + + resname = find_resource_dir_entry( &restype->children, Name ); + if (!resname) + { + resname = HeapAlloc( GetProcessHeap(), 0, sizeof *resname ); + resname->id = res_strdupW( Name ); + list_init( &resname->children ); + add_resource_dir_entry( &restype->children, resname ); + } + + /* + * If there's an existing resource entry with matching (Type,Name,Language) + * it needs to be removed before adding the new data. + */ + existing = find_resource_data( &resname->children, Lang ); + if (existing) + { + if (!overwrite_existing) + return FALSE; + list_remove( &existing->entry ); + HeapFree( GetProcessHeap(), 0, existing ); + } + + if (resdata) + add_resource_data_entry( &resname->children, resdata ); + + return TRUE; +} + +static struct resource_data *allocate_resource_data( WORD Language, DWORD codepage, + LPVOID lpData, DWORD cbData, BOOL copy_data ) +{ + struct resource_data *resdata; + + if (!lpData || !cbData) + return NULL; + + resdata = HeapAlloc( GetProcessHeap(), 0, sizeof *resdata + (copy_data ? cbData : 0) ); + if (resdata) + { + resdata->lang = Language; + resdata->codepage = codepage; + resdata->cbData = cbData; + if (copy_data) + { + resdata->lpData = &resdata[1]; + memcpy( resdata->lpData, lpData, cbData ); + } + else + resdata->lpData = lpData; + } + + return resdata; +} + +static void free_resource_directory( struct list *head, int level ) +{ + struct list *ptr = NULL; + + while ((ptr = list_head( head ))) + { + list_remove( ptr ); + if (level) + { + struct resource_dir_entry *ent; + + ent = LIST_ENTRY( ptr, struct resource_dir_entry, entry ); + res_free_str( ent->id ); + free_resource_directory( &ent->children, level - 1 ); + HeapFree(GetProcessHeap(), 0, ent); + } + else + { + struct resource_data *data; + + data = LIST_ENTRY( ptr, struct resource_data, entry ); + HeapFree( GetProcessHeap(), 0, data ); + } + } +} + +static IMAGE_NT_HEADERS *get_nt_header( void *base, DWORD mapping_size ) +{ + IMAGE_NT_HEADERS *nt; + IMAGE_DOS_HEADER *dos; + + if (mapping_sizee_magic != IMAGE_DOS_SIGNATURE) + return NULL; + + if ((dos->e_lfanew + sizeof (*nt)) > mapping_size) + return NULL; + + nt = (void*) ((BYTE*)base + dos->e_lfanew); + + if (nt->Signature != IMAGE_NT_SIGNATURE) + return NULL; + + return nt; +} + +static IMAGE_SECTION_HEADER *get_section_header( void *base, DWORD mapping_size, DWORD *num_sections ) +{ + IMAGE_NT_HEADERS *nt; + IMAGE_SECTION_HEADER *sec; + DWORD section_ofs; + + nt = get_nt_header( base, mapping_size ); + if (!nt) + return NULL; + + /* check that we don't go over the end of the file accessing the sections */ + section_ofs = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + nt->FileHeader.SizeOfOptionalHeader; + if ((nt->FileHeader.NumberOfSections * sizeof (*sec) + section_ofs) > mapping_size) + return NULL; + + if (num_sections) + *num_sections = nt->FileHeader.NumberOfSections; + + /* from here we have a valid PE exe to update */ + return (void*) ((BYTE*)nt + section_ofs); +} + +static BOOL check_pe_exe( HANDLE file, QUEUEDUPDATES *updates ) +{ + const IMAGE_NT_HEADERS *nt; + const IMAGE_SECTION_HEADER *sec; + BOOL ret = FALSE; + HANDLE mapping; + DWORD mapping_size, num_sections = 0; + void *base = NULL; + + mapping_size = GetFileSize( file, NULL ); + + mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL ); + if (!mapping) + goto done; + + base = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, mapping_size ); + if (!base) + goto done; + + nt = get_nt_header( base, mapping_size ); + if (!nt) + goto done; + + TRACE("resources: %08x %08x\n", + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress, + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size); + + sec = get_section_header( base, mapping_size, &num_sections ); + if (!sec) + goto done; + + ret = TRUE; + +done: + if (base) + UnmapViewOfFile( base ); + if (mapping) + CloseHandle( mapping ); + + return ret; +} + +struct resource_size_info { + DWORD types_ofs; + DWORD names_ofs; + DWORD langs_ofs; + DWORD data_entry_ofs; + DWORD strings_ofs; + DWORD data_ofs; + DWORD total_size; +}; + +struct mapping_info { + HANDLE file; + void *base; + DWORD size; + BOOL read_write; +}; + +static const IMAGE_SECTION_HEADER *section_from_rva( void *base, DWORD mapping_size, DWORD rva ) +{ + const IMAGE_SECTION_HEADER *sec; + DWORD num_sections = 0; + int i; + + sec = get_section_header( base, mapping_size, &num_sections ); + if (!sec) + return NULL; + + for (i=num_sections-1; i>=0; i--) + { + if (sec[i].VirtualAddress <= rva && + rva <= (DWORD)sec[i].VirtualAddress + sec[i].SizeOfRawData) + { + return &sec[i]; + } + } + + return NULL; +} + +static void *address_from_rva( void *base, DWORD mapping_size, DWORD rva, DWORD len ) +{ + const IMAGE_SECTION_HEADER *sec; + + sec = section_from_rva( base, mapping_size, rva ); + if (!sec) + return NULL; + + if (rva + len <= (DWORD)sec->VirtualAddress + sec->SizeOfRawData) + return (void*)((LPBYTE) base + (sec->PointerToRawData + rva - sec->VirtualAddress)); + + return NULL; +} + +static LPWSTR resource_dup_string( const IMAGE_RESOURCE_DIRECTORY *root, const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry ) +{ + const IMAGE_RESOURCE_DIR_STRING_U* string; + LPWSTR s; + + if (!entry->u1.s1.NameIsString) + return UIntToPtr(entry->u1.Id); + + string = (const IMAGE_RESOURCE_DIR_STRING_U*) (((const char *)root) + entry->u1.s1.NameOffset); + s = HeapAlloc(GetProcessHeap(), 0, (string->Length + 1)*sizeof (WCHAR) ); + memcpy( s, string->NameString, (string->Length + 1)*sizeof (WCHAR) ); + s[string->Length] = 0; + + return s; +} + +/* this function is based on the code in winedump's pe.c */ +static BOOL enumerate_mapped_resources( QUEUEDUPDATES *updates, + void *base, DWORD mapping_size, + const IMAGE_RESOURCE_DIRECTORY *root ) +{ + const IMAGE_RESOURCE_DIRECTORY *namedir, *langdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *e1, *e2, *e3; + const IMAGE_RESOURCE_DATA_ENTRY *data; + DWORD i, j, k; + + TRACE("version (%d.%d) %d named %d id entries\n", + root->MajorVersion, root->MinorVersion, root->NumberOfNamedEntries, root->NumberOfIdEntries); + + for (i = 0; i< root->NumberOfNamedEntries + root->NumberOfIdEntries; i++) + { + LPWSTR Type; + + e1 = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(root + 1) + i; + + Type = resource_dup_string( root, e1 ); + + namedir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + e1->u2.s3.OffsetToDirectory); + for (j = 0; j < namedir->NumberOfNamedEntries + namedir->NumberOfIdEntries; j++) + { + LPWSTR Name; + + e2 = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(namedir + 1) + j; + + Name = resource_dup_string( root, e2 ); + + langdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + e2->u2.s3.OffsetToDirectory); + for (k = 0; k < langdir->NumberOfNamedEntries + langdir->NumberOfIdEntries; k++) + { + LANGID Lang; + void *p; + struct resource_data *resdata; + + e3 = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(langdir + 1) + k; + + Lang = e3->u1.Id; + + data = (const IMAGE_RESOURCE_DATA_ENTRY *)((const char *)root + e3->u2.OffsetToData); + + p = address_from_rva( base, mapping_size, data->OffsetToData, data->Size ); + + resdata = allocate_resource_data( Lang, data->CodePage, p, data->Size, FALSE ); + if (resdata) + { + if (!update_add_resource( updates, Type, Name, Lang, resdata, FALSE )) + HeapFree( GetProcessHeap(), 0, resdata ); + } + } + res_free_str( Name ); + } + res_free_str( Type ); + } + + return TRUE; +} + +static BOOL read_mapped_resources( QUEUEDUPDATES *updates, void *base, DWORD mapping_size ) +{ + const IMAGE_RESOURCE_DIRECTORY *root; + const IMAGE_NT_HEADERS *nt; + const IMAGE_SECTION_HEADER *sec; + DWORD num_sections = 0, i; + + nt = get_nt_header( base, mapping_size ); + if (!nt) + return FALSE; + + sec = get_section_header( base, mapping_size, &num_sections ); + if (!sec) + return FALSE; + + for (i=0; i mapping_size || + (sec[i].PointerToRawData + sec[i].SizeOfRawData) > mapping_size) + return TRUE; + + TRACE("found .rsrc at %08x, size %08x\n", sec[i].PointerToRawData, sec[i].SizeOfRawData); + + if (!sec[i].PointerToRawData || sec[i].SizeOfRawData < sizeof(IMAGE_RESOURCE_DIRECTORY)) + return TRUE; + + root = (void*) ((BYTE*)base + sec[i].PointerToRawData); + enumerate_mapped_resources( updates, base, mapping_size, root ); + + return TRUE; +} + +static BOOL map_file_into_memory( struct mapping_info *mi ) +{ + DWORD page_attr, perm; + HANDLE mapping; + + if (mi->read_write) + { + page_attr = PAGE_READWRITE; + perm = FILE_MAP_WRITE | FILE_MAP_READ; + } + else + { + page_attr = PAGE_READONLY; + perm = FILE_MAP_READ; + } + + mapping = CreateFileMappingW( mi->file, NULL, page_attr, 0, 0, NULL ); + if (!mapping) return FALSE; + + mi->base = MapViewOfFile( mapping, perm, 0, 0, mi->size ); + CloseHandle( mapping ); + + return mi->base != NULL; +} + +static BOOL unmap_file_from_memory( struct mapping_info *mi ) +{ + if (mi->base) + UnmapViewOfFile( mi->base ); + mi->base = NULL; + return TRUE; +} + +static void destroy_mapping( struct mapping_info *mi ) +{ + if (!mi) + return; + unmap_file_from_memory( mi ); + if (mi->file) + CloseHandle( mi->file ); + HeapFree( GetProcessHeap(), 0, mi ); +} + +static struct mapping_info *create_mapping( LPCWSTR name, BOOL rw ) +{ + struct mapping_info *mi; + + mi = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *mi ); + if (!mi) + return NULL; + + mi->read_write = rw; + + mi->file = CreateFileW( name, GENERIC_READ | (rw ? GENERIC_WRITE : 0), + 0, NULL, OPEN_EXISTING, 0, 0 ); + + if (mi->file != INVALID_HANDLE_VALUE) + { + mi->size = GetFileSize( mi->file, NULL ); + + if (map_file_into_memory( mi )) + return mi; + } + destroy_mapping( mi ); + return NULL; +} + +static BOOL resize_mapping( struct mapping_info *mi, DWORD new_size ) +{ + if (!unmap_file_from_memory( mi )) + return FALSE; + + /* change the file size */ + SetFilePointer( mi->file, new_size, NULL, FILE_BEGIN ); + if (!SetEndOfFile( mi->file )) + { + ERR("failed to set file size to %08x\n", new_size ); + return FALSE; + } + + mi->size = new_size; + + return map_file_into_memory( mi ); +} + +static void get_resource_sizes( QUEUEDUPDATES *updates, struct resource_size_info *si ) +{ + struct resource_dir_entry *types, *names; + struct resource_data *data; + DWORD num_types = 0, num_names = 0, num_langs = 0, strings_size = 0, data_size = 0; + + memset( si, 0, sizeof *si ); + + LIST_FOR_EACH_ENTRY( types, &updates->root, struct resource_dir_entry, entry ) + { + num_types++; + if (!IS_INTRESOURCE( types->id )) + strings_size += sizeof (WORD) + lstrlenW( types->id )*sizeof (WCHAR); + + LIST_FOR_EACH_ENTRY( names, &types->children, struct resource_dir_entry, entry ) + { + num_names++; + + if (!IS_INTRESOURCE( names->id )) + strings_size += sizeof (WORD) + lstrlenW( names->id )*sizeof (WCHAR); + + LIST_FOR_EACH_ENTRY( data, &names->children, struct resource_data, entry ) + { + num_langs++; + data_size += (data->cbData + 3) & ~3; + } + } + } + + /* names are at the end of the types */ + si->names_ofs = sizeof (IMAGE_RESOURCE_DIRECTORY) + + num_types * sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY); + + /* language directories are at the end of the names */ + si->langs_ofs = si->names_ofs + + num_types * sizeof (IMAGE_RESOURCE_DIRECTORY) + + num_names * sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY); + + si->data_entry_ofs = si->langs_ofs + + num_names * sizeof (IMAGE_RESOURCE_DIRECTORY) + + num_langs * sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY); + + si->strings_ofs = si->data_entry_ofs + + num_langs * sizeof (IMAGE_RESOURCE_DATA_ENTRY); + + si->data_ofs = si->strings_ofs + ((strings_size + 3) & ~3); + + si->total_size = si->data_ofs + data_size; + + TRACE("names %08x langs %08x data entries %08x strings %08x data %08x total %08x\n", + si->names_ofs, si->langs_ofs, si->data_entry_ofs, + si->strings_ofs, si->data_ofs, si->total_size); +} + +static void res_write_padding( BYTE *res_base, DWORD size ) +{ + static const BYTE pad[] = { + 'P','A','D','D','I','N','G','X','X','P','A','D','D','I','N','G' }; + DWORD i; + + for ( i = 0; i < size / sizeof pad; i++ ) + memcpy( &res_base[i*sizeof pad], pad, sizeof pad ); + memcpy( &res_base[i*sizeof pad], pad, size%sizeof pad ); +} + +static BOOL write_resources( QUEUEDUPDATES *updates, LPBYTE base, struct resource_size_info *si, DWORD rva ) +{ + struct resource_dir_entry *types, *names; + struct resource_data *data; + IMAGE_RESOURCE_DIRECTORY *root; + + TRACE("%p %p %p %08x\n", updates, base, si, rva ); + + memset( base, 0, si->total_size ); + + /* the root entry always exists */ + root = (IMAGE_RESOURCE_DIRECTORY*) base; + memset( root, 0, sizeof *root ); + root->MajorVersion = 4; + si->types_ofs = sizeof *root; + LIST_FOR_EACH_ENTRY( types, &updates->root, struct resource_dir_entry, entry ) + { + IMAGE_RESOURCE_DIRECTORY_ENTRY *e1; + IMAGE_RESOURCE_DIRECTORY *namedir; + + e1 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*) &base[si->types_ofs]; + memset( e1, 0, sizeof *e1 ); + if (!IS_INTRESOURCE( types->id )) + { + WCHAR *strings; + DWORD len; + + root->NumberOfNamedEntries++; + e1->u1.s1.NameIsString = 1; + e1->u1.s1.NameOffset = si->strings_ofs; + + strings = (WCHAR*) &base[si->strings_ofs]; + len = lstrlenW( types->id ); + strings[0] = len; + memcpy( &strings[1], types->id, len * sizeof (WCHAR) ); + si->strings_ofs += (len + 1) * sizeof (WCHAR); + } + else + { + root->NumberOfIdEntries++; + e1->u1.Id = LOWORD( types->id ); + } + e1->u2.s3.OffsetToDirectory = si->names_ofs; + e1->u2.s3.DataIsDirectory = TRUE; + si->types_ofs += sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY); + + namedir = (IMAGE_RESOURCE_DIRECTORY*) &base[si->names_ofs]; + memset( namedir, 0, sizeof *namedir ); + namedir->MajorVersion = 4; + si->names_ofs += sizeof (IMAGE_RESOURCE_DIRECTORY); + + LIST_FOR_EACH_ENTRY( names, &types->children, struct resource_dir_entry, entry ) + { + IMAGE_RESOURCE_DIRECTORY_ENTRY *e2; + IMAGE_RESOURCE_DIRECTORY *langdir; + + e2 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*) &base[si->names_ofs]; + memset( e2, 0, sizeof *e2 ); + if (!IS_INTRESOURCE( names->id )) + { + WCHAR *strings; + DWORD len; + + namedir->NumberOfNamedEntries++; + e2->u1.s1.NameIsString = 1; + e2->u1.s1.NameOffset = si->strings_ofs; + + strings = (WCHAR*) &base[si->strings_ofs]; + len = lstrlenW( names->id ); + strings[0] = len; + memcpy( &strings[1], names->id, len * sizeof (WCHAR) ); + si->strings_ofs += (len + 1) * sizeof (WCHAR); + } + else + { + namedir->NumberOfIdEntries++; + e2->u1.Id = LOWORD( names->id ); + } + e2->u2.s3.OffsetToDirectory = si->langs_ofs; + e2->u2.s3.DataIsDirectory = TRUE; + si->names_ofs += sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY); + + langdir = (IMAGE_RESOURCE_DIRECTORY*) &base[si->langs_ofs]; + memset( langdir, 0, sizeof *langdir ); + langdir->MajorVersion = 4; + si->langs_ofs += sizeof (IMAGE_RESOURCE_DIRECTORY); + + LIST_FOR_EACH_ENTRY( data, &names->children, struct resource_data, entry ) + { + IMAGE_RESOURCE_DIRECTORY_ENTRY *e3; + IMAGE_RESOURCE_DATA_ENTRY *de; + int pad_size; + + e3 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*) &base[si->langs_ofs]; + memset( e3, 0, sizeof *e3 ); + langdir->NumberOfIdEntries++; + e3->u1.Id = LOWORD( data->lang ); + e3->u2.OffsetToData = si->data_entry_ofs; + + si->langs_ofs += sizeof (IMAGE_RESOURCE_DIRECTORY_ENTRY); + + /* write out all the data entries */ + de = (IMAGE_RESOURCE_DATA_ENTRY*) &base[si->data_entry_ofs]; + memset( de, 0, sizeof *de ); + de->OffsetToData = si->data_ofs + rva; + de->Size = data->cbData; + de->CodePage = data->codepage; + si->data_entry_ofs += sizeof (IMAGE_RESOURCE_DATA_ENTRY); + + /* write out the resource data */ + memcpy( &base[si->data_ofs], data->lpData, data->cbData ); + si->data_ofs += data->cbData; + + pad_size = (-si->data_ofs)&3; + res_write_padding( &base[si->data_ofs], pad_size ); + si->data_ofs += pad_size; + } + } + } + + return TRUE; +} + +/* + * FIXME: + * Assumes that the resources are in .rsrc + * and .rsrc is the last section in the file. + * Not sure whether updating resources will other cases on Windows. + * If the resources lie in a section containing other data, + * resizing that section could possibly cause trouble. + * If the section with the resources isn't last, the remaining + * sections need to be moved down in the file, and the section header + * would need to be adjusted. + * If we needed to add a section, what would we name it? + * If we needed to add a section and there wasn't space in the file + * header, how would that work? + * Seems that at least some of these cases can't be handled properly. + */ +static IMAGE_SECTION_HEADER *get_resource_section( void *base, DWORD mapping_size ) +{ + IMAGE_SECTION_HEADER *sec; + IMAGE_NT_HEADERS *nt; + DWORD i, num_sections = 0; + + nt = get_nt_header( base, mapping_size ); + if (!nt) + return NULL; + + sec = get_section_header( base, mapping_size, &num_sections ); + if (!sec) + return NULL; + + /* find the resources section */ + for (i=0; ipFileName, tempfile, FALSE )) + goto done; + + TRACE("tempfile %s\n", debugstr_w(tempfile)); + + if (!updates->bDeleteExistingResources) + { + read_map = create_mapping( updates->pFileName, FALSE ); + if (!read_map) + goto done; + + ret = read_mapped_resources( updates, read_map->base, read_map->size ); + if (!ret) + { + ERR("failed to read existing resources\n"); + goto done; + } + } + + write_map = create_mapping( tempfile, TRUE ); + if (!write_map) + goto done; + + nt = get_nt_header( write_map->base, write_map->size ); + if (!nt) + goto done; + + if (nt->OptionalHeader.SectionAlignment <= 0) + { + ERR("invalid section alignment %04x\n", nt->OptionalHeader.SectionAlignment); + goto done; + } + + if (nt->OptionalHeader.FileAlignment <= 0) + { + ERR("invalid file alignment %04x\n", nt->OptionalHeader.FileAlignment); + goto done; + } + + sec = get_resource_section( write_map->base, write_map->size ); + if (!sec) /* no section, add one */ + { + DWORD num_sections; + + sec = get_section_header( write_map->base, write_map->size, &num_sections ); + if (!sec) + goto done; + + sec += num_sections; + nt->FileHeader.NumberOfSections++; + + memset( sec, 0, sizeof *sec ); + memcpy( sec->Name, ".rsrc", 5 ); + sec->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; + sec->VirtualAddress = nt->OptionalHeader.SizeOfImage; + } + + if (!sec->PointerToRawData) /* empty section */ + { + sec->PointerToRawData = write_map->size + (-write_map->size) % nt->OptionalHeader.FileAlignment; + sec->SizeOfRawData = 0; + } + + TRACE("before .rsrc at %08x, size %08x\n", sec->PointerToRawData, sec->SizeOfRawData); + + get_resource_sizes( updates, &res_size ); + + /* round up the section size */ + section_size = res_size.total_size; + section_size += (-section_size) % nt->OptionalHeader.FileAlignment; + + TRACE("requires %08x (%08x) bytes\n", res_size.total_size, section_size ); + + /* check if the file size needs to be changed */ + if (section_size != sec->SizeOfRawData) + { + DWORD old_size = write_map->size; + DWORD virtual_section_size = res_size.total_size + (-res_size.total_size) % nt->OptionalHeader.SectionAlignment; + int delta = section_size - (sec->SizeOfRawData + (-sec->SizeOfRawData) % nt->OptionalHeader.FileAlignment); + int rva_delta = virtual_section_size - + (sec->Misc.VirtualSize + (-sec->Misc.VirtualSize) % nt->OptionalHeader.SectionAlignment); + BOOL rsrc_is_last = sec->PointerToRawData + sec->SizeOfRawData == old_size; + /* align .rsrc size when possible */ + DWORD mapping_size = rsrc_is_last ? sec->PointerToRawData + section_size : old_size + delta; + + /* postpone file truncation if there are some data to be moved down from file end */ + BOOL resize_after = mapping_size < old_size && !rsrc_is_last; + + TRACE("file size %08x -> %08x\n", old_size, mapping_size); + + if (!resize_after) + { + /* unmap the file before changing the file size */ + ret = resize_mapping( write_map, mapping_size ); + + /* get the pointers again - they might be different after remapping */ + nt = get_nt_header( write_map->base, mapping_size ); + if (!nt) + { + ERR("couldn't get NT header\n"); + goto done; + } + + sec = get_resource_section( write_map->base, mapping_size ); + if (!sec) + goto done; + } + + if (!rsrc_is_last) /* not last section, relocate trailing sections */ + { + IMAGE_SECTION_HEADER *s; + DWORD tail_start = sec->PointerToRawData + sec->SizeOfRawData; + DWORD i, num_sections = 0; + + memmove( (char*)write_map->base + tail_start + delta, (char*)write_map->base + tail_start, old_size - tail_start ); + + s = get_section_header( write_map->base, mapping_size, &num_sections ); + + for (i=0; i sec->PointerToRawData) + { + s[i].PointerToRawData += delta; + s[i].VirtualAddress += rva_delta; + } + } + } + + if (resize_after) + { + ret = resize_mapping( write_map, mapping_size ); + + nt = get_nt_header( write_map->base, mapping_size ); + if (!nt) + { + ERR("couldn't get NT header\n"); + goto done; + } + + sec = get_resource_section( write_map->base, mapping_size ); + if (!sec) + goto done; + } + + /* adjust the PE header information */ + sec->SizeOfRawData = section_size; + sec->Misc.VirtualSize = virtual_section_size; + nt->OptionalHeader.SizeOfImage += rva_delta; + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = res_size.total_size; + nt->OptionalHeader.SizeOfInitializedData = get_init_data_size( write_map->base, mapping_size ); + } + + res_base = (LPBYTE) write_map->base + sec->PointerToRawData; + + TRACE("base = %p offset = %08x\n", write_map->base, sec->PointerToRawData); + + ret = write_resources( updates, res_base, &res_size, sec->VirtualAddress ); + + res_write_padding( res_base + res_size.total_size, section_size - res_size.total_size ); + + TRACE("after .rsrc at %08x, size %08x\n", sec->PointerToRawData, sec->SizeOfRawData); + +done: + destroy_mapping( read_map ); + destroy_mapping( write_map ); + + if (ret) + ret = CopyFileW( tempfile, updates->pFileName, FALSE ); + + DeleteFileW( tempfile ); + + return ret; +} + +/*********************************************************************** + * BeginUpdateResourceW (KERNEL32.@) + */ +HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources ) +{ + QUEUEDUPDATES *updates = NULL; + HANDLE hUpdate, file, ret = NULL; + + TRACE("%s, %d\n", debugstr_w(pFileName), bDeleteExistingResources); + + hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES)); + if (!hUpdate) + return ret; + + updates = GlobalLock(hUpdate); + if (updates) + { + list_init( &updates->root ); + updates->bDeleteExistingResources = bDeleteExistingResources; + updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pFileName)+1)*sizeof(WCHAR)); + if (updates->pFileName) + { + lstrcpyW(updates->pFileName, pFileName); + + file = CreateFileW( pFileName, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, 0 ); + + /* if resources are deleted, only the file's presence is checked */ + if (file != INVALID_HANDLE_VALUE && + (bDeleteExistingResources || check_pe_exe( file, updates ))) + ret = hUpdate; + else + HeapFree( GetProcessHeap(), 0, updates->pFileName ); + + CloseHandle( file ); + } + GlobalUnlock(hUpdate); + } + + if (!ret) + GlobalFree(hUpdate); + + return ret; +} + + +/*********************************************************************** + * BeginUpdateResourceA (KERNEL32.@) + */ +HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources ) +{ + UNICODE_STRING FileNameW; + HANDLE ret; + RtlCreateUnicodeStringFromAsciiz(&FileNameW, pFileName); + ret = BeginUpdateResourceW(FileNameW.Buffer, bDeleteExistingResources); + RtlFreeUnicodeString(&FileNameW); + return ret; +} + + +/*********************************************************************** + * EndUpdateResourceW (KERNEL32.@) + */ +BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard ) +{ + QUEUEDUPDATES *updates; + BOOL ret; + + TRACE("%p %d\n", hUpdate, fDiscard); + + updates = GlobalLock(hUpdate); + if (!updates) + return FALSE; + + ret = fDiscard || write_raw_resources( updates ); + + free_resource_directory( &updates->root, 2 ); + + HeapFree( GetProcessHeap(), 0, updates->pFileName ); + GlobalUnlock( hUpdate ); + GlobalFree( hUpdate ); + + return ret; +} + + +/*********************************************************************** + * EndUpdateResourceA (KERNEL32.@) + */ +BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard ) +{ + return EndUpdateResourceW(hUpdate, fDiscard); +} + + +/*********************************************************************** + * UpdateResourceW (KERNEL32.@) + */ +BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName, + WORD wLanguage, LPVOID lpData, DWORD cbData) +{ + QUEUEDUPDATES *updates; + BOOL ret = FALSE; + + TRACE("%p %s %s %08x %p %d\n", hUpdate, + debugstr_w(lpType), debugstr_w(lpName), wLanguage, lpData, cbData); + + updates = GlobalLock(hUpdate); + if (updates) + { + if (lpData == NULL && cbData == 0) /* remove resource */ + { + ret = update_add_resource( updates, lpType, lpName, wLanguage, NULL, TRUE ); + } + else + { + struct resource_data *data; + data = allocate_resource_data( wLanguage, 0, lpData, cbData, TRUE ); + if (data) + ret = update_add_resource( updates, lpType, lpName, wLanguage, data, TRUE ); + } + GlobalUnlock(hUpdate); + } + return ret; +} + + +/*********************************************************************** + * UpdateResourceA (KERNEL32.@) + */ +BOOL WINAPI UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName, + WORD wLanguage, LPVOID lpData, DWORD cbData) +{ + BOOL ret; + UNICODE_STRING TypeW; + UNICODE_STRING NameW; + if(IS_INTRESOURCE(lpType)) + TypeW.Buffer = ULongToPtr(LOWORD(lpType)); + else + RtlCreateUnicodeStringFromAsciiz(&TypeW, lpType); + if(IS_INTRESOURCE(lpName)) + NameW.Buffer = ULongToPtr(LOWORD(lpName)); + else + RtlCreateUnicodeStringFromAsciiz(&NameW, lpName); + ret = UpdateResourceW(hUpdate, TypeW.Buffer, NameW.Buffer, wLanguage, lpData, cbData); + if(!IS_INTRESOURCE(lpType)) RtlFreeUnicodeString(&TypeW); + if(!IS_INTRESOURCE(lpName)) RtlFreeUnicodeString(&NameW); + return ret; +} diff --git a/dll/win32/kernel32/wine/timezone.c b/dll/win32/kernel32/wine/timezone.c new file mode 100644 index 00000000000..44ee45bb5ab --- /dev/null +++ b/dll/win32/kernel32/wine/timezone.c @@ -0,0 +1,382 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/time.c + * PURPOSE: Time conversion functions + * PROGRAMMER: Ariadne + * DOSDATE and DOSTIME structures from Onno Hovers + * UPDATE HISTORY: + * Created 19/01/99 + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* TYPES *********************************************************************/ + +#define TICKSPERMIN 600000000 + +#define LL2FILETIME( ll, pft )\ + (pft)->dwLowDateTime = (UINT)(ll); \ + (pft)->dwHighDateTime = (UINT)((ll) >> 32); +#define FILETIME2LL( pft, ll) \ + ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ; + +static const int MonthLengths[2][12] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +/* STATIC FUNTIONS **********************************************************/ + +static inline int IsLeapYear(int Year) +{ + return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; +} + +/*********************************************************************** + * TIME_DayLightCompareDate + * + * Compares two dates without looking at the year. + * + * PARAMS + * date [in] The local time to compare. + * compareDate [in] The daylight savings begin or end date. + * + * RETURNS + * + * -1 if date < compareDate + * 0 if date == compareDate + * 1 if date > compareDate + * -2 if an error occurs + */ +static int +TIME_DayLightCompareDate(const SYSTEMTIME *date, const SYSTEMTIME *compareDate) +{ + int limit_day, dayinsecs; + + if (date->wMonth < compareDate->wMonth) + return -1; /* We are in a month before the date limit. */ + + if (date->wMonth > compareDate->wMonth) + return 1; /* We are in a month after the date limit. */ + + /* if year is 0 then date is in day-of-week format, otherwise + * it's absolute date. + */ + if (compareDate->wYear == 0) + { + WORD First; + /* compareDate->wDay is interpreted as number of the week in the month + * 5 means: the last week in the month */ + int weekofmonth = compareDate->wDay; + /* calculate the day of the first DayOfWeek in the month */ + First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay + ) % 7 + 1; + limit_day = First + 7 * (weekofmonth - 1); + /* check needed for the 5th weekday of the month */ + if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)] + [date->wMonth - 1]) + limit_day -= 7; + } + else + { + limit_day = compareDate->wDay; + } + + /* convert to seconds */ + limit_day = ((limit_day * 24 + compareDate->wHour) * 60 + + compareDate->wMinute ) * 60; + dayinsecs = ((date->wDay * 24 + date->wHour) * 60 + + date->wMinute ) * 60 + date->wSecond; + /* and compare */ + return dayinsecs < limit_day ? -1 : + dayinsecs > limit_day ? 1 : + 0; /* date is equal to the date limit. */ +} + +/*********************************************************************** + * TIME_CompTimeZoneID + * + * Computes the local time bias for a given time and time zone. + * + * PARAMS + * pTZinfo [in] The time zone data. + * lpFileTime [in] The system or local time. + * islocal [in] it is local time. + * + * RETURNS + * TIME_ZONE_ID_INVALID An error occurred + * TIME_ZONE_ID_UNKNOWN There are no transition time known + * TIME_ZONE_ID_STANDARD Current time is standard time + * TIME_ZONE_ID_DAYLIGHT Current time is daylight savings time + */ +static +DWORD +TIME_CompTimeZoneID( const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal ) +{ + int ret; + BOOL beforeStandardDate, afterDaylightDate; + DWORD retval = TIME_ZONE_ID_INVALID; + LONGLONG llTime = 0; /* initialized to prevent gcc complaining */ + SYSTEMTIME SysTime; + FILETIME ftTemp; + + if (pTZinfo->DaylightDate.wMonth != 0) + { + /* if year is 0 then date is in day-of-week format, otherwise + * it's absolute date. + */ + if (pTZinfo->StandardDate.wMonth == 0 || + (pTZinfo->StandardDate.wYear == 0 && + (pTZinfo->StandardDate.wDay<1 || + pTZinfo->StandardDate.wDay>5 || + pTZinfo->DaylightDate.wDay<1 || + pTZinfo->DaylightDate.wDay>5))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return TIME_ZONE_ID_INVALID; + } + + if (!islocal) { + FILETIME2LL( lpFileTime, llTime ); + llTime -= ( pTZinfo->Bias + pTZinfo->DaylightBias ) + * (LONGLONG)TICKSPERMIN; + LL2FILETIME( llTime, &ftTemp) + lpFileTime = &ftTemp; + } + + FileTimeToSystemTime(lpFileTime, &SysTime); + + /* check for daylight savings */ + ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate); + if (ret == -2) + return TIME_ZONE_ID_INVALID; + + beforeStandardDate = ret < 0; + + if (!islocal) { + llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias ) + * (LONGLONG)TICKSPERMIN; + LL2FILETIME( llTime, &ftTemp) + FileTimeToSystemTime(lpFileTime, &SysTime); + } + + ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate); + if (ret == -2) + return TIME_ZONE_ID_INVALID; + + afterDaylightDate = ret >= 0; + + retval = TIME_ZONE_ID_STANDARD; + if( pTZinfo->DaylightDate.wMonth < pTZinfo->StandardDate.wMonth ) { + /* Northern hemisphere */ + if( beforeStandardDate && afterDaylightDate ) + retval = TIME_ZONE_ID_DAYLIGHT; + } else /* Down south */ + if( beforeStandardDate || afterDaylightDate ) + retval = TIME_ZONE_ID_DAYLIGHT; + } else + /* No transition date */ + retval = TIME_ZONE_ID_UNKNOWN; + + return retval; +} + +/*********************************************************************** + * TIME_TimeZoneID + * + * Calculates whether daylight savings is on now. + * + * PARAMS + * pTzi [in] Timezone info. + * + * RETURNS + * TIME_ZONE_ID_INVALID An error occurred + * TIME_ZONE_ID_UNKNOWN There are no transition time known + * TIME_ZONE_ID_STANDARD Current time is standard time + * TIME_ZONE_ID_DAYLIGHT Current time is daylight savings time + */ +static DWORD TIME_ZoneID( const TIME_ZONE_INFORMATION *pTzi ) +{ + FILETIME ftTime; + GetSystemTimeAsFileTime( &ftTime); + return TIME_CompTimeZoneID( pTzi, &ftTime, FALSE); +} + +/*********************************************************************** + * TIME_GetTimezoneBias + * + * Calculates the local time bias for a given time zone. + * + * PARAMS + * pTZinfo [in] The time zone data. + * lpFileTime [in] The system or local time. + * islocal [in] It is local time. + * pBias [out] The calculated bias in minutes. + * + * RETURNS + * TRUE when the time zone bias was calculated. + */ +static BOOL +TIME_GetTimezoneBias(const TIME_ZONE_INFORMATION *pTZinfo, FILETIME *lpFileTime, BOOL islocal, LONG *pBias) +{ + LONG bias = pTZinfo->Bias; + DWORD tzid = TIME_CompTimeZoneID(pTZinfo, lpFileTime, islocal); + + if( tzid == TIME_ZONE_ID_INVALID) + return FALSE; + if (tzid == TIME_ZONE_ID_DAYLIGHT) + bias += pTZinfo->DaylightBias; + else if (tzid == TIME_ZONE_ID_STANDARD) + bias += pTZinfo->StandardBias; + *pBias = bias; + return TRUE; +} + + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +DWORD +WINAPI +GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) +{ + NTSTATUS Status; + + DPRINT("GetTimeZoneInformation()\n"); + + Status = NtQuerySystemInformation(SystemCurrentTimeZoneInformation, + lpTimeZoneInformation, + sizeof(TIME_ZONE_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return TIME_ZONE_ID_INVALID; + } + + return TIME_ZoneID(lpTimeZoneInformation); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation) +{ + NTSTATUS Status; + + DPRINT("SetTimeZoneInformation()\n"); + + Status = RtlSetTimeZoneInformation((LPTIME_ZONE_INFORMATION)lpTimeZoneInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlSetTimeZoneInformation() failed (Status %lx)\n", Status); + BaseSetLastNTError(Status); + return FALSE; + } + + Status = NtSetSystemInformation(SystemCurrentTimeZoneInformation, + (PVOID)lpTimeZoneInformation, + sizeof(TIME_ZONE_INFORMATION)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtSetSystemInformation() failed (Status %lx)\n", Status); + BaseSetLastNTError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation, + CONST SYSTEMTIME *lpUniversalTime, + LPSYSTEMTIME lpLocalTime) +{ + TIME_ZONE_INFORMATION TzInfo; + FILETIME FileTime; + LONGLONG llTime; + LONG lBias; + + if (lpTimeZoneInformation != NULL) + { + TzInfo = *lpTimeZoneInformation; + } + else + { + if (GetTimeZoneInformation(&TzInfo) == TIME_ZONE_ID_INVALID) + return FALSE; + } + + if (!lpUniversalTime || !lpLocalTime) + return FALSE; + + if (!SystemTimeToFileTime(lpUniversalTime, &FileTime)) + return FALSE; + + FILETIME2LL(&FileTime, llTime) + + if (!TIME_GetTimezoneBias(&TzInfo, &FileTime, FALSE, &lBias)) + return FALSE; + + /* convert minutes to 100-nanoseconds-ticks */ + llTime -= (LONGLONG)lBias * TICKSPERMIN; + + LL2FILETIME( llTime, &FileTime) + + return FileTimeToSystemTime(&FileTime, lpLocalTime); +} + + +/* + * @implemented (Wine 13 sep 2008) + */ +BOOL +WINAPI +TzSpecificLocalTimeToSystemTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, + LPSYSTEMTIME lpLocalTime, + LPSYSTEMTIME lpUniversalTime) +{ + FILETIME ft; + LONG lBias; + LONGLONG t; + TIME_ZONE_INFORMATION tzinfo; + + if (lpTimeZoneInformation != NULL) + { + tzinfo = *lpTimeZoneInformation; + } + else + { + if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID) + return FALSE; + } + + if (!SystemTimeToFileTime(lpLocalTime, &ft)) + return FALSE; + FILETIME2LL( &ft, t) + if (!TIME_GetTimezoneBias(&tzinfo, &ft, TRUE, &lBias)) + return FALSE; + /* convert minutes to 100-nanoseconds-ticks */ + t += (LONGLONG)lBias * TICKSPERMIN; + LL2FILETIME( t, &ft) + return FileTimeToSystemTime(&ft, lpUniversalTime); +} + +/* EOF */ diff --git a/dll/win32/kernel32/lang/bg-BG.mc b/dll/win32/kernel32/winnls/lang/bg-BG.mc similarity index 100% rename from dll/win32/kernel32/lang/bg-BG.mc rename to dll/win32/kernel32/winnls/lang/bg-BG.mc diff --git a/dll/win32/kernel32/lang/de-DE.mc b/dll/win32/kernel32/winnls/lang/de-DE.mc similarity index 100% rename from dll/win32/kernel32/lang/de-DE.mc rename to dll/win32/kernel32/winnls/lang/de-DE.mc diff --git a/dll/win32/kernel32/lang/de-DE.rc b/dll/win32/kernel32/winnls/lang/de-DE.rc similarity index 100% rename from dll/win32/kernel32/lang/de-DE.rc rename to dll/win32/kernel32/winnls/lang/de-DE.rc diff --git a/dll/win32/kernel32/lang/en-US.rc b/dll/win32/kernel32/winnls/lang/en-US.rc similarity index 100% rename from dll/win32/kernel32/lang/en-US.rc rename to dll/win32/kernel32/winnls/lang/en-US.rc diff --git a/dll/win32/kernel32/lang/es-ES.rc b/dll/win32/kernel32/winnls/lang/es-ES.rc similarity index 100% rename from dll/win32/kernel32/lang/es-ES.rc rename to dll/win32/kernel32/winnls/lang/es-ES.rc diff --git a/dll/win32/kernel32/lang/pl-PL.mc b/dll/win32/kernel32/winnls/lang/pl-PL.mc similarity index 100% rename from dll/win32/kernel32/lang/pl-PL.mc rename to dll/win32/kernel32/winnls/lang/pl-PL.mc diff --git a/dll/win32/kernel32/lang/ru-RU.mc b/dll/win32/kernel32/winnls/lang/ru-RU.mc similarity index 100% rename from dll/win32/kernel32/lang/ru-RU.mc rename to dll/win32/kernel32/winnls/lang/ru-RU.mc diff --git a/dll/win32/kernel32/lang/ru-RU.rc b/dll/win32/kernel32/winnls/lang/ru-RU.rc similarity index 100% rename from dll/win32/kernel32/lang/ru-RU.rc rename to dll/win32/kernel32/winnls/lang/ru-RU.rc diff --git a/dll/win32/kernel32/lang/uk-UA.rc b/dll/win32/kernel32/winnls/lang/uk-UA.rc similarity index 100% rename from dll/win32/kernel32/lang/uk-UA.rc rename to dll/win32/kernel32/winnls/lang/uk-UA.rc diff --git a/dll/win32/kernel32/locale_rc.rc b/dll/win32/kernel32/winnls/locale_rc.rc similarity index 100% rename from dll/win32/kernel32/locale_rc.rc rename to dll/win32/kernel32/winnls/locale_rc.rc diff --git a/dll/win32/kernel32/nls/afk.nls b/dll/win32/kernel32/winnls/nls/afk.nls similarity index 100% rename from dll/win32/kernel32/nls/afk.nls rename to dll/win32/kernel32/winnls/nls/afk.nls diff --git a/dll/win32/kernel32/nls/ara.nls b/dll/win32/kernel32/winnls/nls/ara.nls similarity index 100% rename from dll/win32/kernel32/nls/ara.nls rename to dll/win32/kernel32/winnls/nls/ara.nls diff --git a/dll/win32/kernel32/nls/arb.nls b/dll/win32/kernel32/winnls/nls/arb.nls similarity index 100% rename from dll/win32/kernel32/nls/arb.nls rename to dll/win32/kernel32/winnls/nls/arb.nls diff --git a/dll/win32/kernel32/nls/are.nls b/dll/win32/kernel32/winnls/nls/are.nls similarity index 100% rename from dll/win32/kernel32/nls/are.nls rename to dll/win32/kernel32/winnls/nls/are.nls diff --git a/dll/win32/kernel32/nls/arg.nls b/dll/win32/kernel32/winnls/nls/arg.nls similarity index 100% rename from dll/win32/kernel32/nls/arg.nls rename to dll/win32/kernel32/winnls/nls/arg.nls diff --git a/dll/win32/kernel32/nls/arh.nls b/dll/win32/kernel32/winnls/nls/arh.nls similarity index 100% rename from dll/win32/kernel32/nls/arh.nls rename to dll/win32/kernel32/winnls/nls/arh.nls diff --git a/dll/win32/kernel32/nls/ari.nls b/dll/win32/kernel32/winnls/nls/ari.nls similarity index 100% rename from dll/win32/kernel32/nls/ari.nls rename to dll/win32/kernel32/winnls/nls/ari.nls diff --git a/dll/win32/kernel32/nls/arj.nls b/dll/win32/kernel32/winnls/nls/arj.nls similarity index 100% rename from dll/win32/kernel32/nls/arj.nls rename to dll/win32/kernel32/winnls/nls/arj.nls diff --git a/dll/win32/kernel32/nls/ark.nls b/dll/win32/kernel32/winnls/nls/ark.nls similarity index 100% rename from dll/win32/kernel32/nls/ark.nls rename to dll/win32/kernel32/winnls/nls/ark.nls diff --git a/dll/win32/kernel32/nls/arl.nls b/dll/win32/kernel32/winnls/nls/arl.nls similarity index 100% rename from dll/win32/kernel32/nls/arl.nls rename to dll/win32/kernel32/winnls/nls/arl.nls diff --git a/dll/win32/kernel32/nls/arm.nls b/dll/win32/kernel32/winnls/nls/arm.nls similarity index 100% rename from dll/win32/kernel32/nls/arm.nls rename to dll/win32/kernel32/winnls/nls/arm.nls diff --git a/dll/win32/kernel32/nls/aro.nls b/dll/win32/kernel32/winnls/nls/aro.nls similarity index 100% rename from dll/win32/kernel32/nls/aro.nls rename to dll/win32/kernel32/winnls/nls/aro.nls diff --git a/dll/win32/kernel32/nls/arq.nls b/dll/win32/kernel32/winnls/nls/arq.nls similarity index 100% rename from dll/win32/kernel32/nls/arq.nls rename to dll/win32/kernel32/winnls/nls/arq.nls diff --git a/dll/win32/kernel32/nls/ars.nls b/dll/win32/kernel32/winnls/nls/ars.nls similarity index 100% rename from dll/win32/kernel32/nls/ars.nls rename to dll/win32/kernel32/winnls/nls/ars.nls diff --git a/dll/win32/kernel32/nls/art.nls b/dll/win32/kernel32/winnls/nls/art.nls similarity index 100% rename from dll/win32/kernel32/nls/art.nls rename to dll/win32/kernel32/winnls/nls/art.nls diff --git a/dll/win32/kernel32/nls/aru.nls b/dll/win32/kernel32/winnls/nls/aru.nls similarity index 100% rename from dll/win32/kernel32/nls/aru.nls rename to dll/win32/kernel32/winnls/nls/aru.nls diff --git a/dll/win32/kernel32/nls/ary.nls b/dll/win32/kernel32/winnls/nls/ary.nls similarity index 100% rename from dll/win32/kernel32/nls/ary.nls rename to dll/win32/kernel32/winnls/nls/ary.nls diff --git a/dll/win32/kernel32/nls/aze.nls b/dll/win32/kernel32/winnls/nls/aze.nls similarity index 100% rename from dll/win32/kernel32/nls/aze.nls rename to dll/win32/kernel32/winnls/nls/aze.nls diff --git a/dll/win32/kernel32/nls/azl.nls b/dll/win32/kernel32/winnls/nls/azl.nls similarity index 100% rename from dll/win32/kernel32/nls/azl.nls rename to dll/win32/kernel32/winnls/nls/azl.nls diff --git a/dll/win32/kernel32/nls/bel.nls b/dll/win32/kernel32/winnls/nls/bel.nls similarity index 100% rename from dll/win32/kernel32/nls/bel.nls rename to dll/win32/kernel32/winnls/nls/bel.nls diff --git a/dll/win32/kernel32/nls/bgr.nls b/dll/win32/kernel32/winnls/nls/bgr.nls similarity index 100% rename from dll/win32/kernel32/nls/bgr.nls rename to dll/win32/kernel32/winnls/nls/bgr.nls diff --git a/dll/win32/kernel32/nls/brf.nls b/dll/win32/kernel32/winnls/nls/brf.nls similarity index 100% rename from dll/win32/kernel32/nls/brf.nls rename to dll/win32/kernel32/winnls/nls/brf.nls diff --git a/dll/win32/kernel32/nls/cat.nls b/dll/win32/kernel32/winnls/nls/cat.nls similarity index 100% rename from dll/win32/kernel32/nls/cat.nls rename to dll/win32/kernel32/winnls/nls/cat.nls diff --git a/dll/win32/kernel32/nls/chs.nls b/dll/win32/kernel32/winnls/nls/chs.nls similarity index 100% rename from dll/win32/kernel32/nls/chs.nls rename to dll/win32/kernel32/winnls/nls/chs.nls diff --git a/dll/win32/kernel32/nls/cht.nls b/dll/win32/kernel32/winnls/nls/cht.nls similarity index 100% rename from dll/win32/kernel32/nls/cht.nls rename to dll/win32/kernel32/winnls/nls/cht.nls diff --git a/dll/win32/kernel32/nls/csy.nls b/dll/win32/kernel32/winnls/nls/csy.nls similarity index 100% rename from dll/win32/kernel32/nls/csy.nls rename to dll/win32/kernel32/winnls/nls/csy.nls diff --git a/dll/win32/kernel32/nls/cym.nls b/dll/win32/kernel32/winnls/nls/cym.nls similarity index 100% rename from dll/win32/kernel32/nls/cym.nls rename to dll/win32/kernel32/winnls/nls/cym.nls diff --git a/dll/win32/kernel32/nls/dan.nls b/dll/win32/kernel32/winnls/nls/dan.nls similarity index 100% rename from dll/win32/kernel32/nls/dan.nls rename to dll/win32/kernel32/winnls/nls/dan.nls diff --git a/dll/win32/kernel32/nls/dea.nls b/dll/win32/kernel32/winnls/nls/dea.nls similarity index 100% rename from dll/win32/kernel32/nls/dea.nls rename to dll/win32/kernel32/winnls/nls/dea.nls diff --git a/dll/win32/kernel32/nls/dec.nls b/dll/win32/kernel32/winnls/nls/dec.nls similarity index 100% rename from dll/win32/kernel32/nls/dec.nls rename to dll/win32/kernel32/winnls/nls/dec.nls diff --git a/dll/win32/kernel32/nls/del.nls b/dll/win32/kernel32/winnls/nls/del.nls similarity index 100% rename from dll/win32/kernel32/nls/del.nls rename to dll/win32/kernel32/winnls/nls/del.nls diff --git a/dll/win32/kernel32/nls/des.nls b/dll/win32/kernel32/winnls/nls/des.nls similarity index 100% rename from dll/win32/kernel32/nls/des.nls rename to dll/win32/kernel32/winnls/nls/des.nls diff --git a/dll/win32/kernel32/nls/deu.nls b/dll/win32/kernel32/winnls/nls/deu.nls similarity index 100% rename from dll/win32/kernel32/nls/deu.nls rename to dll/win32/kernel32/winnls/nls/deu.nls diff --git a/dll/win32/kernel32/nls/div.nls b/dll/win32/kernel32/winnls/nls/div.nls similarity index 100% rename from dll/win32/kernel32/nls/div.nls rename to dll/win32/kernel32/winnls/nls/div.nls diff --git a/dll/win32/kernel32/nls/ell.nls b/dll/win32/kernel32/winnls/nls/ell.nls similarity index 100% rename from dll/win32/kernel32/nls/ell.nls rename to dll/win32/kernel32/winnls/nls/ell.nls diff --git a/dll/win32/kernel32/nls/ena.nls b/dll/win32/kernel32/winnls/nls/ena.nls similarity index 100% rename from dll/win32/kernel32/nls/ena.nls rename to dll/win32/kernel32/winnls/nls/ena.nls diff --git a/dll/win32/kernel32/nls/enb.nls b/dll/win32/kernel32/winnls/nls/enb.nls similarity index 100% rename from dll/win32/kernel32/nls/enb.nls rename to dll/win32/kernel32/winnls/nls/enb.nls diff --git a/dll/win32/kernel32/nls/enc.nls b/dll/win32/kernel32/winnls/nls/enc.nls similarity index 100% rename from dll/win32/kernel32/nls/enc.nls rename to dll/win32/kernel32/winnls/nls/enc.nls diff --git a/dll/win32/kernel32/nls/eng.nls b/dll/win32/kernel32/winnls/nls/eng.nls similarity index 100% rename from dll/win32/kernel32/nls/eng.nls rename to dll/win32/kernel32/winnls/nls/eng.nls diff --git a/dll/win32/kernel32/nls/eni.nls b/dll/win32/kernel32/winnls/nls/eni.nls similarity index 100% rename from dll/win32/kernel32/nls/eni.nls rename to dll/win32/kernel32/winnls/nls/eni.nls diff --git a/dll/win32/kernel32/nls/enj.nls b/dll/win32/kernel32/winnls/nls/enj.nls similarity index 100% rename from dll/win32/kernel32/nls/enj.nls rename to dll/win32/kernel32/winnls/nls/enj.nls diff --git a/dll/win32/kernel32/nls/enl.nls b/dll/win32/kernel32/winnls/nls/enl.nls similarity index 100% rename from dll/win32/kernel32/nls/enl.nls rename to dll/win32/kernel32/winnls/nls/enl.nls diff --git a/dll/win32/kernel32/nls/enp.nls b/dll/win32/kernel32/winnls/nls/enp.nls similarity index 100% rename from dll/win32/kernel32/nls/enp.nls rename to dll/win32/kernel32/winnls/nls/enp.nls diff --git a/dll/win32/kernel32/nls/ens.nls b/dll/win32/kernel32/winnls/nls/ens.nls similarity index 100% rename from dll/win32/kernel32/nls/ens.nls rename to dll/win32/kernel32/winnls/nls/ens.nls diff --git a/dll/win32/kernel32/nls/ent.nls b/dll/win32/kernel32/winnls/nls/ent.nls similarity index 100% rename from dll/win32/kernel32/nls/ent.nls rename to dll/win32/kernel32/winnls/nls/ent.nls diff --git a/dll/win32/kernel32/nls/enu.nls b/dll/win32/kernel32/winnls/nls/enu.nls similarity index 100% rename from dll/win32/kernel32/nls/enu.nls rename to dll/win32/kernel32/winnls/nls/enu.nls diff --git a/dll/win32/kernel32/nls/enw.nls b/dll/win32/kernel32/winnls/nls/enw.nls similarity index 100% rename from dll/win32/kernel32/nls/enw.nls rename to dll/win32/kernel32/winnls/nls/enw.nls diff --git a/dll/win32/kernel32/nls/enz.nls b/dll/win32/kernel32/winnls/nls/enz.nls similarity index 100% rename from dll/win32/kernel32/nls/enz.nls rename to dll/win32/kernel32/winnls/nls/enz.nls diff --git a/dll/win32/kernel32/nls/esa.nls b/dll/win32/kernel32/winnls/nls/esa.nls similarity index 100% rename from dll/win32/kernel32/nls/esa.nls rename to dll/win32/kernel32/winnls/nls/esa.nls diff --git a/dll/win32/kernel32/nls/esb.nls b/dll/win32/kernel32/winnls/nls/esb.nls similarity index 100% rename from dll/win32/kernel32/nls/esb.nls rename to dll/win32/kernel32/winnls/nls/esb.nls diff --git a/dll/win32/kernel32/nls/esc.nls b/dll/win32/kernel32/winnls/nls/esc.nls similarity index 100% rename from dll/win32/kernel32/nls/esc.nls rename to dll/win32/kernel32/winnls/nls/esc.nls diff --git a/dll/win32/kernel32/nls/esd.nls b/dll/win32/kernel32/winnls/nls/esd.nls similarity index 100% rename from dll/win32/kernel32/nls/esd.nls rename to dll/win32/kernel32/winnls/nls/esd.nls diff --git a/dll/win32/kernel32/nls/ese.nls b/dll/win32/kernel32/winnls/nls/ese.nls similarity index 100% rename from dll/win32/kernel32/nls/ese.nls rename to dll/win32/kernel32/winnls/nls/ese.nls diff --git a/dll/win32/kernel32/nls/esf.nls b/dll/win32/kernel32/winnls/nls/esf.nls similarity index 100% rename from dll/win32/kernel32/nls/esf.nls rename to dll/win32/kernel32/winnls/nls/esf.nls diff --git a/dll/win32/kernel32/nls/esg.nls b/dll/win32/kernel32/winnls/nls/esg.nls similarity index 100% rename from dll/win32/kernel32/nls/esg.nls rename to dll/win32/kernel32/winnls/nls/esg.nls diff --git a/dll/win32/kernel32/nls/esh.nls b/dll/win32/kernel32/winnls/nls/esh.nls similarity index 100% rename from dll/win32/kernel32/nls/esh.nls rename to dll/win32/kernel32/winnls/nls/esh.nls diff --git a/dll/win32/kernel32/nls/esi.nls b/dll/win32/kernel32/winnls/nls/esi.nls similarity index 100% rename from dll/win32/kernel32/nls/esi.nls rename to dll/win32/kernel32/winnls/nls/esi.nls diff --git a/dll/win32/kernel32/nls/esl.nls b/dll/win32/kernel32/winnls/nls/esl.nls similarity index 100% rename from dll/win32/kernel32/nls/esl.nls rename to dll/win32/kernel32/winnls/nls/esl.nls diff --git a/dll/win32/kernel32/nls/esm.nls b/dll/win32/kernel32/winnls/nls/esm.nls similarity index 100% rename from dll/win32/kernel32/nls/esm.nls rename to dll/win32/kernel32/winnls/nls/esm.nls diff --git a/dll/win32/kernel32/nls/esn.nls b/dll/win32/kernel32/winnls/nls/esn.nls similarity index 100% rename from dll/win32/kernel32/nls/esn.nls rename to dll/win32/kernel32/winnls/nls/esn.nls diff --git a/dll/win32/kernel32/nls/eso.nls b/dll/win32/kernel32/winnls/nls/eso.nls similarity index 100% rename from dll/win32/kernel32/nls/eso.nls rename to dll/win32/kernel32/winnls/nls/eso.nls diff --git a/dll/win32/kernel32/nls/esp.nls b/dll/win32/kernel32/winnls/nls/esp.nls similarity index 100% rename from dll/win32/kernel32/nls/esp.nls rename to dll/win32/kernel32/winnls/nls/esp.nls diff --git a/dll/win32/kernel32/nls/esr.nls b/dll/win32/kernel32/winnls/nls/esr.nls similarity index 100% rename from dll/win32/kernel32/nls/esr.nls rename to dll/win32/kernel32/winnls/nls/esr.nls diff --git a/dll/win32/kernel32/nls/ess.nls b/dll/win32/kernel32/winnls/nls/ess.nls similarity index 100% rename from dll/win32/kernel32/nls/ess.nls rename to dll/win32/kernel32/winnls/nls/ess.nls diff --git a/dll/win32/kernel32/nls/esu.nls b/dll/win32/kernel32/winnls/nls/esu.nls similarity index 100% rename from dll/win32/kernel32/nls/esu.nls rename to dll/win32/kernel32/winnls/nls/esu.nls diff --git a/dll/win32/kernel32/nls/esv.nls b/dll/win32/kernel32/winnls/nls/esv.nls similarity index 100% rename from dll/win32/kernel32/nls/esv.nls rename to dll/win32/kernel32/winnls/nls/esv.nls diff --git a/dll/win32/kernel32/nls/esy.nls b/dll/win32/kernel32/winnls/nls/esy.nls similarity index 100% rename from dll/win32/kernel32/nls/esy.nls rename to dll/win32/kernel32/winnls/nls/esy.nls diff --git a/dll/win32/kernel32/nls/esz.nls b/dll/win32/kernel32/winnls/nls/esz.nls similarity index 100% rename from dll/win32/kernel32/nls/esz.nls rename to dll/win32/kernel32/winnls/nls/esz.nls diff --git a/dll/win32/kernel32/nls/eti.nls b/dll/win32/kernel32/winnls/nls/eti.nls similarity index 100% rename from dll/win32/kernel32/nls/eti.nls rename to dll/win32/kernel32/winnls/nls/eti.nls diff --git a/dll/win32/kernel32/nls/euq.nls b/dll/win32/kernel32/winnls/nls/euq.nls similarity index 100% rename from dll/win32/kernel32/nls/euq.nls rename to dll/win32/kernel32/winnls/nls/euq.nls diff --git a/dll/win32/kernel32/nls/far.nls b/dll/win32/kernel32/winnls/nls/far.nls similarity index 100% rename from dll/win32/kernel32/nls/far.nls rename to dll/win32/kernel32/winnls/nls/far.nls diff --git a/dll/win32/kernel32/nls/fin.nls b/dll/win32/kernel32/winnls/nls/fin.nls similarity index 100% rename from dll/win32/kernel32/nls/fin.nls rename to dll/win32/kernel32/winnls/nls/fin.nls diff --git a/dll/win32/kernel32/nls/fos.nls b/dll/win32/kernel32/winnls/nls/fos.nls similarity index 100% rename from dll/win32/kernel32/nls/fos.nls rename to dll/win32/kernel32/winnls/nls/fos.nls diff --git a/dll/win32/kernel32/nls/fra.nls b/dll/win32/kernel32/winnls/nls/fra.nls similarity index 100% rename from dll/win32/kernel32/nls/fra.nls rename to dll/win32/kernel32/winnls/nls/fra.nls diff --git a/dll/win32/kernel32/nls/frb.nls b/dll/win32/kernel32/winnls/nls/frb.nls similarity index 100% rename from dll/win32/kernel32/nls/frb.nls rename to dll/win32/kernel32/winnls/nls/frb.nls diff --git a/dll/win32/kernel32/nls/frc.nls b/dll/win32/kernel32/winnls/nls/frc.nls similarity index 100% rename from dll/win32/kernel32/nls/frc.nls rename to dll/win32/kernel32/winnls/nls/frc.nls diff --git a/dll/win32/kernel32/nls/frl.nls b/dll/win32/kernel32/winnls/nls/frl.nls similarity index 100% rename from dll/win32/kernel32/nls/frl.nls rename to dll/win32/kernel32/winnls/nls/frl.nls diff --git a/dll/win32/kernel32/nls/frm.nls b/dll/win32/kernel32/winnls/nls/frm.nls similarity index 100% rename from dll/win32/kernel32/nls/frm.nls rename to dll/win32/kernel32/winnls/nls/frm.nls diff --git a/dll/win32/kernel32/nls/frs.nls b/dll/win32/kernel32/winnls/nls/frs.nls similarity index 100% rename from dll/win32/kernel32/nls/frs.nls rename to dll/win32/kernel32/winnls/nls/frs.nls diff --git a/dll/win32/kernel32/nls/glc.nls b/dll/win32/kernel32/winnls/nls/glc.nls similarity index 100% rename from dll/win32/kernel32/nls/glc.nls rename to dll/win32/kernel32/winnls/nls/glc.nls diff --git a/dll/win32/kernel32/nls/guj.nls b/dll/win32/kernel32/winnls/nls/guj.nls similarity index 100% rename from dll/win32/kernel32/nls/guj.nls rename to dll/win32/kernel32/winnls/nls/guj.nls diff --git a/dll/win32/kernel32/nls/heb.nls b/dll/win32/kernel32/winnls/nls/heb.nls similarity index 100% rename from dll/win32/kernel32/nls/heb.nls rename to dll/win32/kernel32/winnls/nls/heb.nls diff --git a/dll/win32/kernel32/nls/hin.nls b/dll/win32/kernel32/winnls/nls/hin.nls similarity index 100% rename from dll/win32/kernel32/nls/hin.nls rename to dll/win32/kernel32/winnls/nls/hin.nls diff --git a/dll/win32/kernel32/nls/hrv.nls b/dll/win32/kernel32/winnls/nls/hrv.nls similarity index 100% rename from dll/win32/kernel32/nls/hrv.nls rename to dll/win32/kernel32/winnls/nls/hrv.nls diff --git a/dll/win32/kernel32/nls/hun.nls b/dll/win32/kernel32/winnls/nls/hun.nls similarity index 100% rename from dll/win32/kernel32/nls/hun.nls rename to dll/win32/kernel32/winnls/nls/hun.nls diff --git a/dll/win32/kernel32/nls/hye.nls b/dll/win32/kernel32/winnls/nls/hye.nls similarity index 100% rename from dll/win32/kernel32/nls/hye.nls rename to dll/win32/kernel32/winnls/nls/hye.nls diff --git a/dll/win32/kernel32/nls/ind.nls b/dll/win32/kernel32/winnls/nls/ind.nls similarity index 100% rename from dll/win32/kernel32/nls/ind.nls rename to dll/win32/kernel32/winnls/nls/ind.nls diff --git a/dll/win32/kernel32/nls/isl.nls b/dll/win32/kernel32/winnls/nls/isl.nls similarity index 100% rename from dll/win32/kernel32/nls/isl.nls rename to dll/win32/kernel32/winnls/nls/isl.nls diff --git a/dll/win32/kernel32/nls/ita.nls b/dll/win32/kernel32/winnls/nls/ita.nls similarity index 100% rename from dll/win32/kernel32/nls/ita.nls rename to dll/win32/kernel32/winnls/nls/ita.nls diff --git a/dll/win32/kernel32/nls/its.nls b/dll/win32/kernel32/winnls/nls/its.nls similarity index 100% rename from dll/win32/kernel32/nls/its.nls rename to dll/win32/kernel32/winnls/nls/its.nls diff --git a/dll/win32/kernel32/nls/jpn.nls b/dll/win32/kernel32/winnls/nls/jpn.nls similarity index 100% rename from dll/win32/kernel32/nls/jpn.nls rename to dll/win32/kernel32/winnls/nls/jpn.nls diff --git a/dll/win32/kernel32/nls/kan.nls b/dll/win32/kernel32/winnls/nls/kan.nls similarity index 100% rename from dll/win32/kernel32/nls/kan.nls rename to dll/win32/kernel32/winnls/nls/kan.nls diff --git a/dll/win32/kernel32/nls/kat.nls b/dll/win32/kernel32/winnls/nls/kat.nls similarity index 100% rename from dll/win32/kernel32/nls/kat.nls rename to dll/win32/kernel32/winnls/nls/kat.nls diff --git a/dll/win32/kernel32/nls/kkz.nls b/dll/win32/kernel32/winnls/nls/kkz.nls similarity index 100% rename from dll/win32/kernel32/nls/kkz.nls rename to dll/win32/kernel32/winnls/nls/kkz.nls diff --git a/dll/win32/kernel32/nls/knk.nls b/dll/win32/kernel32/winnls/nls/knk.nls similarity index 100% rename from dll/win32/kernel32/nls/knk.nls rename to dll/win32/kernel32/winnls/nls/knk.nls diff --git a/dll/win32/kernel32/nls/kor.nls b/dll/win32/kernel32/winnls/nls/kor.nls similarity index 100% rename from dll/win32/kernel32/nls/kor.nls rename to dll/win32/kernel32/winnls/nls/kor.nls diff --git a/dll/win32/kernel32/nls/kyr.nls b/dll/win32/kernel32/winnls/nls/kyr.nls similarity index 100% rename from dll/win32/kernel32/nls/kyr.nls rename to dll/win32/kernel32/winnls/nls/kyr.nls diff --git a/dll/win32/kernel32/nls/lth.nls b/dll/win32/kernel32/winnls/nls/lth.nls similarity index 100% rename from dll/win32/kernel32/nls/lth.nls rename to dll/win32/kernel32/winnls/nls/lth.nls diff --git a/dll/win32/kernel32/nls/lvi.nls b/dll/win32/kernel32/winnls/nls/lvi.nls similarity index 100% rename from dll/win32/kernel32/nls/lvi.nls rename to dll/win32/kernel32/winnls/nls/lvi.nls diff --git a/dll/win32/kernel32/nls/mar.nls b/dll/win32/kernel32/winnls/nls/mar.nls similarity index 100% rename from dll/win32/kernel32/nls/mar.nls rename to dll/win32/kernel32/winnls/nls/mar.nls diff --git a/dll/win32/kernel32/nls/mki.nls b/dll/win32/kernel32/winnls/nls/mki.nls similarity index 100% rename from dll/win32/kernel32/nls/mki.nls rename to dll/win32/kernel32/winnls/nls/mki.nls diff --git a/dll/win32/kernel32/nls/mon.nls b/dll/win32/kernel32/winnls/nls/mon.nls similarity index 100% rename from dll/win32/kernel32/nls/mon.nls rename to dll/win32/kernel32/winnls/nls/mon.nls diff --git a/dll/win32/kernel32/nls/msb.nls b/dll/win32/kernel32/winnls/nls/msb.nls similarity index 100% rename from dll/win32/kernel32/nls/msb.nls rename to dll/win32/kernel32/winnls/nls/msb.nls diff --git a/dll/win32/kernel32/nls/msl.nls b/dll/win32/kernel32/winnls/nls/msl.nls similarity index 100% rename from dll/win32/kernel32/nls/msl.nls rename to dll/win32/kernel32/winnls/nls/msl.nls diff --git a/dll/win32/kernel32/nls/nlb.nls b/dll/win32/kernel32/winnls/nls/nlb.nls similarity index 100% rename from dll/win32/kernel32/nls/nlb.nls rename to dll/win32/kernel32/winnls/nls/nlb.nls diff --git a/dll/win32/kernel32/nls/nld.nls b/dll/win32/kernel32/winnls/nls/nld.nls similarity index 100% rename from dll/win32/kernel32/nls/nld.nls rename to dll/win32/kernel32/winnls/nls/nld.nls diff --git a/dll/win32/kernel32/nls/non.nls b/dll/win32/kernel32/winnls/nls/non.nls similarity index 100% rename from dll/win32/kernel32/nls/non.nls rename to dll/win32/kernel32/winnls/nls/non.nls diff --git a/dll/win32/kernel32/nls/nor.nls b/dll/win32/kernel32/winnls/nls/nor.nls similarity index 100% rename from dll/win32/kernel32/nls/nor.nls rename to dll/win32/kernel32/winnls/nls/nor.nls diff --git a/dll/win32/kernel32/nls/pan.nls b/dll/win32/kernel32/winnls/nls/pan.nls similarity index 100% rename from dll/win32/kernel32/nls/pan.nls rename to dll/win32/kernel32/winnls/nls/pan.nls diff --git a/dll/win32/kernel32/nls/plk.nls b/dll/win32/kernel32/winnls/nls/plk.nls similarity index 100% rename from dll/win32/kernel32/nls/plk.nls rename to dll/win32/kernel32/winnls/nls/plk.nls diff --git a/dll/win32/kernel32/nls/ptb.nls b/dll/win32/kernel32/winnls/nls/ptb.nls similarity index 100% rename from dll/win32/kernel32/nls/ptb.nls rename to dll/win32/kernel32/winnls/nls/ptb.nls diff --git a/dll/win32/kernel32/nls/ptg.nls b/dll/win32/kernel32/winnls/nls/ptg.nls similarity index 100% rename from dll/win32/kernel32/nls/ptg.nls rename to dll/win32/kernel32/winnls/nls/ptg.nls diff --git a/dll/win32/kernel32/nls/rmc.nls b/dll/win32/kernel32/winnls/nls/rmc.nls similarity index 100% rename from dll/win32/kernel32/nls/rmc.nls rename to dll/win32/kernel32/winnls/nls/rmc.nls diff --git a/dll/win32/kernel32/nls/rom.nls b/dll/win32/kernel32/winnls/nls/rom.nls similarity index 100% rename from dll/win32/kernel32/nls/rom.nls rename to dll/win32/kernel32/winnls/nls/rom.nls diff --git a/dll/win32/kernel32/nls/rus.nls b/dll/win32/kernel32/winnls/nls/rus.nls similarity index 100% rename from dll/win32/kernel32/nls/rus.nls rename to dll/win32/kernel32/winnls/nls/rus.nls diff --git a/dll/win32/kernel32/nls/san.nls b/dll/win32/kernel32/winnls/nls/san.nls similarity index 100% rename from dll/win32/kernel32/nls/san.nls rename to dll/win32/kernel32/winnls/nls/san.nls diff --git a/dll/win32/kernel32/nls/sky.nls b/dll/win32/kernel32/winnls/nls/sky.nls similarity index 100% rename from dll/win32/kernel32/nls/sky.nls rename to dll/win32/kernel32/winnls/nls/sky.nls diff --git a/dll/win32/kernel32/nls/slv.nls b/dll/win32/kernel32/winnls/nls/slv.nls similarity index 100% rename from dll/win32/kernel32/nls/slv.nls rename to dll/win32/kernel32/winnls/nls/slv.nls diff --git a/dll/win32/kernel32/nls/sqi.nls b/dll/win32/kernel32/winnls/nls/sqi.nls similarity index 100% rename from dll/win32/kernel32/nls/sqi.nls rename to dll/win32/kernel32/winnls/nls/sqi.nls diff --git a/dll/win32/kernel32/nls/srb.nls b/dll/win32/kernel32/winnls/nls/srb.nls similarity index 100% rename from dll/win32/kernel32/nls/srb.nls rename to dll/win32/kernel32/winnls/nls/srb.nls diff --git a/dll/win32/kernel32/nls/srl.nls b/dll/win32/kernel32/winnls/nls/srl.nls similarity index 100% rename from dll/win32/kernel32/nls/srl.nls rename to dll/win32/kernel32/winnls/nls/srl.nls diff --git a/dll/win32/kernel32/nls/sve.nls b/dll/win32/kernel32/winnls/nls/sve.nls similarity index 100% rename from dll/win32/kernel32/nls/sve.nls rename to dll/win32/kernel32/winnls/nls/sve.nls diff --git a/dll/win32/kernel32/nls/svf.nls b/dll/win32/kernel32/winnls/nls/svf.nls similarity index 100% rename from dll/win32/kernel32/nls/svf.nls rename to dll/win32/kernel32/winnls/nls/svf.nls diff --git a/dll/win32/kernel32/nls/swk.nls b/dll/win32/kernel32/winnls/nls/swk.nls similarity index 100% rename from dll/win32/kernel32/nls/swk.nls rename to dll/win32/kernel32/winnls/nls/swk.nls diff --git a/dll/win32/kernel32/nls/syr.nls b/dll/win32/kernel32/winnls/nls/syr.nls similarity index 100% rename from dll/win32/kernel32/nls/syr.nls rename to dll/win32/kernel32/winnls/nls/syr.nls diff --git a/dll/win32/kernel32/nls/tam.nls b/dll/win32/kernel32/winnls/nls/tam.nls similarity index 100% rename from dll/win32/kernel32/nls/tam.nls rename to dll/win32/kernel32/winnls/nls/tam.nls diff --git a/dll/win32/kernel32/nls/tel.nls b/dll/win32/kernel32/winnls/nls/tel.nls similarity index 100% rename from dll/win32/kernel32/nls/tel.nls rename to dll/win32/kernel32/winnls/nls/tel.nls diff --git a/dll/win32/kernel32/nls/tha.nls b/dll/win32/kernel32/winnls/nls/tha.nls similarity index 100% rename from dll/win32/kernel32/nls/tha.nls rename to dll/win32/kernel32/winnls/nls/tha.nls diff --git a/dll/win32/kernel32/nls/trk.nls b/dll/win32/kernel32/winnls/nls/trk.nls similarity index 100% rename from dll/win32/kernel32/nls/trk.nls rename to dll/win32/kernel32/winnls/nls/trk.nls diff --git a/dll/win32/kernel32/nls/ttt.nls b/dll/win32/kernel32/winnls/nls/ttt.nls similarity index 100% rename from dll/win32/kernel32/nls/ttt.nls rename to dll/win32/kernel32/winnls/nls/ttt.nls diff --git a/dll/win32/kernel32/nls/ukr.nls b/dll/win32/kernel32/winnls/nls/ukr.nls similarity index 100% rename from dll/win32/kernel32/nls/ukr.nls rename to dll/win32/kernel32/winnls/nls/ukr.nls diff --git a/dll/win32/kernel32/nls/urd.nls b/dll/win32/kernel32/winnls/nls/urd.nls similarity index 100% rename from dll/win32/kernel32/nls/urd.nls rename to dll/win32/kernel32/winnls/nls/urd.nls diff --git a/dll/win32/kernel32/nls/uzb.nls b/dll/win32/kernel32/winnls/nls/uzb.nls similarity index 100% rename from dll/win32/kernel32/nls/uzb.nls rename to dll/win32/kernel32/winnls/nls/uzb.nls diff --git a/dll/win32/kernel32/nls/uzl.nls b/dll/win32/kernel32/winnls/nls/uzl.nls similarity index 100% rename from dll/win32/kernel32/nls/uzl.nls rename to dll/win32/kernel32/winnls/nls/uzl.nls diff --git a/dll/win32/kernel32/nls/vit.nls b/dll/win32/kernel32/winnls/nls/vit.nls similarity index 100% rename from dll/win32/kernel32/nls/vit.nls rename to dll/win32/kernel32/winnls/nls/vit.nls diff --git a/dll/win32/kernel32/nls/zhh.nls b/dll/win32/kernel32/winnls/nls/zhh.nls similarity index 100% rename from dll/win32/kernel32/nls/zhh.nls rename to dll/win32/kernel32/winnls/nls/zhh.nls diff --git a/dll/win32/kernel32/nls/zhi.nls b/dll/win32/kernel32/winnls/nls/zhi.nls similarity index 100% rename from dll/win32/kernel32/nls/zhi.nls rename to dll/win32/kernel32/winnls/nls/zhi.nls diff --git a/dll/win32/kernel32/nls/zhm.nls b/dll/win32/kernel32/winnls/nls/zhm.nls similarity index 100% rename from dll/win32/kernel32/nls/zhm.nls rename to dll/win32/kernel32/winnls/nls/zhm.nls diff --git a/dll/win32/kernel32/winnls/string/casemap.c b/dll/win32/kernel32/winnls/string/casemap.c new file mode 100644 index 00000000000..141a4172675 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/casemap.c @@ -0,0 +1,1992 @@ +/* Unicode case mappings */ +/* Automatically generated; DO NOT EDIT!! */ + +#include "wine/unicode.h" + +const WCHAR wine_casemap_lower[3802] = +{ + /* index */ + 0x01bf, 0x02bf, 0x03bf, 0x044f, 0x054f, 0x064f, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x06af, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x07af, 0x08ae, + 0x0100, 0x09ab, 0x0100, 0x0100, 0x0a2f, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0b2f, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0c1d, 0x0cfb, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0dda, + /* defaults */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0041 .. 0x00ff */ + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0100 .. 0x01ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0xff39, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0xff87, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x00d2, 0x0001, 0x0000, 0x0001, 0x0000, 0x00ce, 0x0001, + 0x0000, 0x00cd, 0x00cd, 0x0001, 0x0000, 0x0000, 0x004f, 0x00ca, + 0x00cb, 0x0001, 0x0000, 0x00cd, 0x00cf, 0x0000, 0x00d3, 0x00d1, + 0x0001, 0x0000, 0x0000, 0x0000, 0x00d3, 0x00d5, 0x0000, 0x00d6, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x00da, 0x0001, + 0x0000, 0x00da, 0x0000, 0x0000, 0x0001, 0x0000, 0x00da, 0x0001, + 0x0000, 0x00d9, 0x00d9, 0x0001, 0x0000, 0x0001, 0x0000, 0x00db, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0002, + 0x0001, 0x0000, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0xff9f, 0xffc8, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + /* 0x0200 .. 0x02ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0xff7e, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x2a2b, 0x0001, 0x0000, 0xff5d, 0x2a28, 0x0000, + 0x0000, 0x0001, 0x0000, 0xff3d, 0x0045, 0x0047, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0370 .. 0x03ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0026, 0x0000, + 0x0025, 0x0025, 0x0025, 0x0000, 0x0040, 0x0000, 0x003f, 0x003f, + 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffc4, 0x0000, 0x0000, 0x0001, + 0x0000, 0xfff9, 0x0001, 0x0000, 0x0000, 0xff7e, 0xff7e, 0xff7e, + /* 0x0400 .. 0x04ff */ + 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, + 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x000f, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + /* 0x0500 .. 0x05ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x10a0 .. 0x10ff */ + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, + 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1e00 .. 0x1eff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe241, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + /* 0x1f01 .. 0x1fff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff8, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0xfff8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xffb6, 0xffb6, 0xfff7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffaa, + 0xffaa, 0xffaa, 0xffaa, 0xfff7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xff9c, 0xff9c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfff8, + 0xfff8, 0xff90, 0xff90, 0xfff9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff80, + 0xff80, 0xff82, 0xff82, 0xfff7, 0x0000, 0x0000, 0x0000, + /* 0x2103 .. 0x21ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xe2a3, 0x0000, 0x0000, 0x0000, 0xdf41, + 0xdfba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x001c, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x247c .. 0x24ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x2c00 .. 0x2cff */ + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0xd609, 0xf11a, 0xd619, 0x0000, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0xd5e4, 0xd603, 0xd5e1, + 0xd5e2, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd5c1, 0xd5c1, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa612 .. 0xa6ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa722 .. 0xa7ff */ + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, + 0x0000, 0x0001, 0x0000, 0x75fc, 0x0001, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xff21 .. 0xffff */ + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, + 0x0020, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; +const WCHAR wine_casemap_upper[3994] = +{ + /* index */ + 0x019f, 0x029f, 0x039f, 0x045a, 0x0556, 0x0656, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x06dd, 0x07dc, 0x08dc, + 0x0100, 0x09d0, 0x0100, 0x0100, 0x0a55, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0b3f, 0x0c3f, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0cfe, 0x0ddb, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0e9a, + /* defaults */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0061 .. 0x00ff */ + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x02e7, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0x0000, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0x0079, + /* 0x0100 .. 0x01ff */ + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xff18, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xfed4, + 0x00c3, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0061, 0x0000, 0x0000, + 0x0000, 0xffff, 0x00a3, 0x0000, 0x0000, 0x0000, 0x0082, 0x0000, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0038, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xfffe, 0x0000, + 0xffff, 0xfffe, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0xffb1, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0xffff, 0xfffe, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + /* 0x0200 .. 0x02ff */ + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x2a3f, + 0x2a3f, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x2a1f, 0x2a1c, 0x2a1e, 0xff2e, 0xff32, 0x0000, 0xff33, 0xff33, + 0x0000, 0xff36, 0x0000, 0xff35, 0x0000, 0x0000, 0x0000, 0x0000, + 0xff33, 0x0000, 0x0000, 0xff31, 0x0000, 0x0000, 0x0000, 0x0000, + 0xff2f, 0xff2d, 0x0000, 0x29f7, 0x0000, 0x0000, 0x0000, 0xff2d, + 0x0000, 0x29fd, 0xff2b, 0x0000, 0x0000, 0xff2a, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x29e7, 0x0000, 0x0000, + 0xff26, 0x0000, 0x0000, 0xff26, 0x0000, 0x0000, 0x0000, 0x0000, + 0xff26, 0xffbb, 0xff27, 0xff27, 0xffb9, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xff25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0345 .. 0x03ff */ + 0x0054, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0082, 0x0082, + 0x0082, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffda, + 0xffdb, 0xffdb, 0xffdb, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe1, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffc0, + 0xffc1, 0xffc1, 0x0000, 0xffc2, 0xffc7, 0x0000, 0x0000, 0x0000, + 0xffd1, 0xffca, 0xfff8, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0xffaa, 0xffb0, 0x0007, 0x0000, 0x0000, + 0xffa0, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, + /* 0x0404 .. 0x04ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, + 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0xffb0, + 0xffb0, 0xffb0, 0xffb0, 0xffb0, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0xfff1, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, + /* 0x0500 .. 0x05ff */ + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1d79 .. 0x1dff */ + 0x8a04, 0x0000, 0x0000, 0x0000, 0x0ee6, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1e01 .. 0x1eff */ + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffc5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + /* 0x1f00 .. 0x1fff */ + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0008, 0x0000, 0x0008, 0x0000, 0x0008, 0x0000, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x004a, 0x004a, 0x0056, 0x0056, 0x0056, 0x0056, 0x0064, 0x0064, + 0x0080, 0x0080, 0x0070, 0x0070, 0x007e, 0x007e, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3db, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0007, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x210c .. 0x21ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffe4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0xfff0, + 0xfff0, 0xfff0, 0xfff0, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x247b .. 0x24ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffe6, 0xffe6, 0xffe6, + 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, + 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, + 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0xffe6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x2c16 .. 0x2cff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, + 0xffd0, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xd5d5, + 0xd5d8, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x2d00 .. 0x2dff */ + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, + 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa641 .. 0xa6ff */ + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa723 .. 0xa7ff */ + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, + 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, + 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, + 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xff41 .. 0xffff */ + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, + 0xffe0, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; +const WCHAR wine_digitmap[5837] = +{ + /* index */ + 0x01d0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x028a, 0x0384, + 0x0100, 0x044e, 0x053e, 0x062e, 0x071e, 0x080e, 0x08be, 0x099e, + 0x0a5e, 0x0100, 0x0100, 0x0af8, 0x0100, 0x0100, 0x0100, 0x0b6a, + 0x0c5a, 0x0d14, 0x0def, 0x0e9f, 0x0f5f, 0x0100, 0x0100, 0x0100, + 0x0fef, 0x0100, 0x0100, 0x0100, 0x108f, 0x0100, 0x0100, 0x118f, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x126f, 0x0100, + 0x129f, 0x139f, 0x1479, 0x14d3, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x15cd, + /* defaults */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0030 .. 0x00ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xff80, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xff78, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0646 .. 0x06ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xf9d0, 0xf9d0, 0xf9d0, 0xf9d0, 0xf9d0, 0xf9d0, + 0xf9d0, 0xf9d0, 0xf9d0, 0xf9d0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xf940, 0xf940, 0xf940, 0xf940, 0xf940, 0xf940, + 0xf940, 0xf940, 0xf940, 0xf940, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x0706 .. 0x07ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xf870, 0xf870, 0xf870, 0xf870, 0xf870, 0xf870, + 0xf870, 0xf870, 0xf870, 0xf870, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x0936 .. 0x09ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xf6ca, 0xf6ca, 0xf6ca, 0xf6ca, 0xf6ca, 0xf6ca, 0xf6ca, 0xf6ca, + 0xf6ca, 0xf6ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xf64a, 0xf64a, 0xf64a, 0xf64a, 0xf64a, 0xf64a, 0xf64a, 0xf64a, + 0xf64a, 0xf64a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x0a10 .. 0x0aff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf5ca, 0xf5ca, + 0xf5ca, 0xf5ca, 0xf5ca, 0xf5ca, 0xf5ca, 0xf5ca, 0xf5ca, 0xf5ca, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf54a, 0xf54a, + 0xf54a, 0xf54a, 0xf54a, 0xf54a, 0xf54a, 0xf54a, 0xf54a, 0xf54a, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0b10 .. 0x0bff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf4ca, 0xf4ca, + 0xf4ca, 0xf4ca, 0xf4ca, 0xf4ca, 0xf4ca, 0xf4ca, 0xf4ca, 0xf4ca, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf44a, 0xf44a, + 0xf44a, 0xf44a, 0xf44a, 0xf44a, 0xf44a, 0xf44a, 0xf44a, 0xf44a, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0c10 .. 0x0cff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf3ca, 0xf3ca, + 0xf3ca, 0xf3ca, 0xf3ca, 0xf3ca, 0xf3ca, 0xf3ca, 0xf3ca, 0xf3ca, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf34a, 0xf34a, + 0xf34a, 0xf34a, 0xf34a, 0xf34a, 0xf34a, 0xf34a, 0xf34a, 0xf34a, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0d10 .. 0x0dff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf2ca, 0xf2ca, + 0xf2ca, 0xf2ca, 0xf2ca, 0xf2ca, 0xf2ca, 0xf2ca, 0xf2ca, 0xf2ca, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0e50 .. 0x0eff */ + 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, + 0xf1e0, 0xf1e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xf160, 0xf160, 0xf160, 0xf160, 0xf160, 0xf160, 0xf160, 0xf160, + 0xf160, 0xf160, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x0f20 .. 0x0fff */ + 0xf110, 0xf110, 0xf110, 0xf110, 0xf110, 0xf110, 0xf110, 0xf110, + 0xf110, 0xf110, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1040 .. 0x10ff */ + 0xeff0, 0xeff0, 0xeff0, 0xeff0, 0xeff0, 0xeff0, 0xeff0, 0xeff0, + 0xeff0, 0xeff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xefa0, 0xefa0, 0xefa0, 0xefa0, 0xefa0, 0xefa0, 0xefa0, 0xefa0, + 0xefa0, 0xefa0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1366 .. 0x13ff */ + 0x0000, 0x0000, 0x0000, 0xecc8, 0xecc8, 0xecc8, 0xecc8, 0xecc8, + 0xecc8, 0xecc8, 0xecc8, 0xecc8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x178e .. 0x17ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xe850, 0xe850, 0xe850, 0xe850, 0xe850, 0xe850, + 0xe850, 0xe850, 0xe850, 0xe850, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x1810 .. 0x18ff */ + 0xe820, 0xe820, 0xe820, 0xe820, 0xe820, 0xe820, 0xe820, 0xe820, + 0xe820, 0xe820, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1946 .. 0x19ff */ + 0xe6ea, 0xe6ea, 0xe6ea, 0xe6ea, 0xe6ea, 0xe6ea, 0xe6ea, 0xe6ea, + 0xe6ea, 0xe6ea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xe660, 0xe660, 0xe660, 0xe660, 0xe660, 0xe660, + 0xe660, 0xe660, 0xe660, 0xe660, 0xe657, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0x1a25 .. 0x1aff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xe5b0, 0xe5b0, 0xe5b0, 0xe5b0, 0xe5b0, + 0xe5b0, 0xe5b0, 0xe5b0, 0xe5b0, 0xe5b0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xe5a0, 0xe5a0, 0xe5a0, 0xe5a0, 0xe5a0, + 0xe5a0, 0xe5a0, 0xe5a0, 0xe5a0, 0xe5a0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, + /* 0x1b50 .. 0x1bff */ + 0xe4e0, 0xe4e0, 0xe4e0, 0xe4e0, 0xe4e0, 0xe4e0, 0xe4e0, 0xe4e0, + 0xe4e0, 0xe4e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xe480, 0xe480, 0xe480, 0xe480, 0xe480, 0xe480, 0xe480, 0xe480, + 0xe480, 0xe480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x1c40 .. 0x1cff */ + 0xe3f0, 0xe3f0, 0xe3f0, 0xe3f0, 0xe3f0, 0xe3f0, 0xe3f0, 0xe3f0, + 0xe3f0, 0xe3f0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xe3e0, 0xe3e0, 0xe3e0, 0xe3e0, 0xe3e0, 0xe3e0, 0xe3e0, 0xe3e0, + 0xe3e0, 0xe3e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x2070 .. 0x20ff */ + 0xdfc0, 0x0000, 0x0000, 0x0000, 0xdfc0, 0xdfc0, 0xdfc0, 0xdfc0, + 0xdfc0, 0xdfc0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xdfb0, 0xdfb0, 0xdfb0, 0xdfb0, 0xdfb0, 0xdfb0, 0xdfb0, 0xdfb0, + 0xdfb0, 0xdfb0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0x2460 .. 0x24ff */ + 0xdbd1, 0xdbd1, 0xdbd1, 0xdbd1, 0xdbd1, 0xdbd1, 0xdbd1, 0xdbd1, + 0xdbd1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xdbbd, 0xdbbd, 0xdbbd, 0xdbbd, + 0xdbbd, 0xdbbd, 0xdbbd, 0xdbbd, 0xdbbd, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xdba9, 0xdba9, 0xdba9, 0xdba9, 0xdba9, 0xdba9, 0xdba9, 0xdba9, + 0xdba9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xdb46, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xdb3c, 0xdb3c, 0xdb3c, + 0xdb3c, 0xdb3c, 0xdb3c, 0xdb3c, 0xdb3c, 0xdb3c, 0x0000, 0xdb31, + /* 0x2700 .. 0x27ff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd8bb, 0xd8bb, + 0xd8bb, 0xd8bb, 0xd8bb, 0xd8bb, 0xd8bb, 0xd8bb, 0xd8bb, 0x0000, + 0xd8b1, 0xd8b1, 0xd8b1, 0xd8b1, 0xd8b1, 0xd8b1, 0xd8b1, 0xd8b1, + 0xd8b1, 0x0000, 0xd8a7, 0xd8a7, 0xd8a7, 0xd8a7, 0xd8a7, 0xd8a7, + 0xd8a7, 0xd8a7, 0xd8a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa620 .. 0xa6ff */ + 0x5a10, 0x5a10, 0x5a10, 0x5a10, 0x5a10, 0x5a10, 0x5a10, 0x5a10, + 0x5a10, 0x5a10, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa8d0 .. 0xa8ff */ + 0x5760, 0x5760, 0x5760, 0x5760, 0x5760, 0x5760, 0x5760, 0x5760, + 0x5760, 0x5760, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xa900 .. 0xa9ff */ + 0x5730, 0x5730, 0x5730, 0x5730, 0x5730, 0x5730, 0x5730, 0x5730, + 0x5730, 0x5730, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x5660, 0x5660, 0x5660, 0x5660, 0x5660, 0x5660, 0x5660, 0x5660, + 0x5660, 0x5660, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xaa26 .. 0xaaff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x55e0, 0x55e0, 0x55e0, 0x55e0, 0x55e0, 0x55e0, + 0x55e0, 0x55e0, 0x55e0, 0x55e0, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0xaba6 .. 0xabff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x5440, 0x5440, 0x5440, 0x5440, 0x5440, 0x5440, + 0x5440, 0x5440, 0x5440, 0x5440, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0xff06 .. 0xffff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000 +}; +const WCHAR wine_compatmap[1497] = +{ + /* index */ + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0200, 0x0300, 0x0100, 0x0100, 0x0100, 0x03da, 0x04d9, + /* defaults */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xf900 .. 0xf9ff */ + 0x9348, 0x6df3, 0x95c8, 0x93c5, 0x75cd, 0x552d, 0x5adf, 0xa695, + 0xa694, 0x6048, 0x98c7, 0x5c7c, 0x603c, 0x68e9, 0x7d5b, 0x8676, + 0x8d2f, 0x8ea9, 0x8fe6, 0x977c, 0x70ee, 0x7406, 0x77c3, 0x7ac7, + 0x8b25, 0x9851, 0xa0d7, 0x5567, 0x5a59, 0x71e7, 0x78fd, 0x8d0e, + 0xa4fe, 0x642f, 0x76c9, 0x8caa, 0x9040, 0x69a4, 0x88b2, 0x8ef8, + 0x65a2, 0x6dee, 0x7440, 0x79d1, 0x97a2, 0x5659, 0x5889, 0x59af, + 0x6b94, 0x71a2, 0x78de, 0x7db4, 0x86cd, 0x8cd1, 0x8d26, 0x94b8, + 0x9dfa, 0xa236, 0xa4c0, 0x7f51, 0x8043, 0x8463, 0x8a8b, 0x99c5, + 0xa53f, 0x9195, 0x5f9d, 0x65c1, 0x831c, 0x8739, 0x791c, 0x7f83, + 0x937a, 0x9dae, 0x5f8e, 0x6317, 0x70c7, 0x748d, 0x75c1, 0x83e0, + 0x84e7, 0x9cfa, 0x5980, 0x8738, 0x5888, 0x5877, 0x80c6, 0x8467, + 0x8a99, 0x9d1c, 0x9226, 0x6974, 0x70a6, 0x91a1, 0x54db, 0x6288, + 0x66b2, 0x7a26, 0x7c0e, 0x59b4, 0x7f97, 0x565a, 0x6643, 0x54a6, + 0x7364, 0x6c0f, 0x83b8, 0x5a58, 0x5ef2, 0x7d94, 0x8adb, 0x913b, + 0x724a, 0x963f, 0x7316, 0x698b, 0x8971, 0x6a2b, 0x7bef, 0x5537, + 0x57f1, 0x5850, 0x6f07, 0x836c, 0x88f3, 0x9155, 0x9851, 0x5976, + 0x5ac2, 0x5ff2, 0x656a, 0x6c42, 0x767a, 0x7fa5, 0x9c27, 0xa0e3, + 0xa50f, 0xa545, 0x5911, 0x6d3b, 0x71eb, 0x95d5, 0x64e6, 0x6801, + 0x6870, 0x6b09, 0x7591, 0x77b6, 0x7af5, 0x8035, 0x845e, 0x86d8, + 0x958e, 0x8b55, 0x9689, 0x99af, 0x587b, 0x5906, 0x5b1f, 0x7729, + 0x8f22, 0x9109, 0x6527, 0x6652, 0x69d7, 0x7209, 0x8298, 0x79ce, + 0x553c, 0x5d50, 0x623d, 0x640f, 0x6670, 0x7a05, 0x7abb, 0x85eb, + 0x8696, 0x9883, 0x9d44, 0x9d95, 0x9e64, 0x55d6, 0x7ff8, 0x97fd, + 0x9d00, 0x6728, 0x54cc, 0x571f, 0x6232, 0x6282, 0x6bdb, 0x7043, + 0x780e, 0x7c81, 0x8b3a, 0x96b9, 0xa5c9, 0x6cc3, 0x9c68, 0x58c2, + 0x6db3, 0x6e2a, 0x7377, 0x74d1, 0x7a3d, 0x7b8c, 0x7e9d, 0x8341, + 0x9e8e, 0x579c, 0x685c, 0x9ca5, 0x5657, 0x6344, 0x7414, 0x9553, + 0x65b3, 0x676b, 0x6e3d, 0x79ac, 0x9caa, 0x584c, 0x5a31, 0x6286, + 0x6c33, 0x6d6d, 0x6ec6, 0x7302, 0x7a22, 0x7bfd, 0x8593, 0x8ee8, + 0x8ef9, 0x97e3, 0x9cf8, 0x5954, 0x74ce, 0x5a30, 0x77e2, 0x7aa9, + 0x8c0a, 0x9cb2, 0xa265, 0xa4ac, 0x6da3, 0x73d6, 0x87f2, 0x80d4, + 0x8128, 0x8299, 0x78c6, 0x769e, 0x915c, 0x54c3, 0x8938, 0x583b, + /* 0xfa00 .. 0xfaff */ + 0x5807, 0x64a5, 0x68d1, 0x82d3, 0x6181, 0x7319, 0x6cae, 0x9534, + 0x8e44, 0x9c44, 0x8f81, 0x64c8, 0x5734, 0x5bb3, 0x0000, 0x0000, + 0x5e4a, 0x0000, 0x6c62, 0x0000, 0x0000, 0x57c9, 0x7914, 0x7cb3, + 0x7f24, 0x7f45, 0x7f4b, 0x7f74, 0x9d3a, 0x82a1, 0x859f, 0x0000, + 0x8bf2, 0x0000, 0x90d6, 0x0000, 0x0000, 0x9613, 0x96d7, 0x0000, + 0x0000, 0x0000, 0x9ec5, 0x9ed1, 0x9efc, 0xa387, 0x0000, 0x0000, + 0x557e, 0x56b6, 0x571b, 0x5896, 0x58b0, 0x591c, 0x5b67, 0x5bcf, + 0x5c30, 0x5e07, 0x5e6e, 0x6229, 0x6232, 0x6657, 0x672a, 0x674f, + 0x67b2, 0x6b0e, 0x6ba0, 0x6c4e, 0x6e41, 0x7332, 0x73d4, 0x74db, + 0x7726, 0x77e2, 0x79d8, 0x7e46, 0x7ef2, 0x7efc, 0x7efa, 0x7f01, + 0x7f06, 0x7f0c, 0x7f3b, 0x7f3b, 0x7fec, 0x802c, 0x816a, 0x839d, + 0x83b1, 0x83e8, 0x8518, 0x85aa, 0x8791, 0x881c, 0x881b, 0x89f8, + 0x8eb0, 0x8f35, 0x909f, 0x90d6, 0x926f, 0x92a3, 0x9550, 0x95d1, + 0x9c7b, 0x9d96, 0x9dd1, 0x660a, 0x4882, 0x87ab, 0x0000, 0x0000, + 0x53b6, 0x5744, 0x56f6, 0x550d, 0x56d1, 0x570b, 0x5851, 0x5883, + 0x5b25, 0x5adc, 0x5b1f, 0x5b67, 0x5dde, 0x5e36, 0x5ec6, 0x5ed5, + 0x5fe2, 0x60a7, 0x6450, 0x6456, 0x64e5, 0x6528, 0x6652, 0x66c7, + 0x6680, 0x6705, 0x66d6, 0x6767, 0x67a8, 0x6937, 0x698e, 0x69c3, + 0x6ac6, 0x6be3, 0x6c85, 0x6c88, 0x6cc2, 0x70e4, 0x7124, 0x72aa, + 0x7443, 0x7432, 0x7488, 0x7583, 0x76d2, 0x7d0a, 0x7797, 0x7810, + 0x788a, 0x79d0, 0x7a64, 0x7a98, 0x7b79, 0x7b7a, 0x7c24, 0x7c34, + 0x7c4c, 0x7ca1, 0x7c96, 0x7e21, 0x8005, 0x8113, 0x81cd, 0x82ac, + 0x8344, 0x848d, 0x8553, 0x889f, 0x893b, 0x8cc4, 0x8e8b, 0x8ecf, + 0x8ede, 0x9006, 0x903e, 0x9010, 0x9045, 0x9041, 0x902f, 0x907a, + 0x90ca, 0x9247, 0x9476, 0x95af, 0x96d5, 0x97b1, 0x9bb6, 0x9c1c, + 0x9c8e, 0x9d12, 0x9d35, 0x9d40, 0x9d6f, 0xa045, 0xa4ce, 0x2d7b, + 0x2d74, 0x3904, 0x40cb, 0x4545, 0x4565, 0x5774, 0x61fa, 0x83fc, + 0xa46b, 0xa4b5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 0xfe26 .. 0xfeff */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x21f5, 0x21e3, 0x21e1, 0x022c, 0x022b, 0x01f3, + 0x01f3, 0x0244, 0x0245, 0x31db, 0x31db, 0x31d5, 0x31d5, 0x31cd, + 0x31cd, 0x31c9, 0x31c9, 0x31cb, 0x31cb, 0x31cb, 0x31cb, 0x0000, + 0x0000, 0x0214, 0x0215, 0x21f5, 0x21f4, 0x21f3, 0x21f2, 0x0212, + 0x0211, 0x0210, 0x01dc, 0x31b0, 0x01dc, 0x0000, 0x01e7, 0x01e5, + 0x01e9, 0x01ca, 0x21bc, 0x01cf, 0x01cf, 0x0220, 0x0221, 0x31b7, + 0x31b7, 0x01c4, 0x01c6, 0x01c9, 0x01c9, 0x01ca, 0x01d8, 0x01d9, + 0x01d7, 0x0000, 0x01f4, 0x01bb, 0x01bb, 0x01d5, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x07a1, 0x07a1, 0x07a0, 0x07a0, 0x079f, 0x079f, + 0x079e, 0x079e, 0x079d, 0x079d, 0x079c, 0x079b, 0x079a, 0x079a, + 0x0799, 0x0799, 0x0798, 0x0797, 0x0796, 0x0796, 0x0795, 0x0795, + 0x0794, 0x0793, 0x0792, 0x0792, 0x0791, 0x0790, 0x078f, 0x078f, + 0x078e, 0x078d, 0x078c, 0x078c, 0x078b, 0x078a, 0x0789, 0x0789, + 0x0788, 0x0787, 0x0786, 0x0786, 0x0785, 0x0785, 0x0784, 0x0784, + 0x0783, 0x0783, 0x0782, 0x0782, 0x0781, 0x0780, 0x077f, 0x077f, + 0x077e, 0x077d, 0x077c, 0x077c, 0x077b, 0x077a, 0x0779, 0x0779, + 0x0778, 0x0777, 0x0776, 0x0776, 0x0775, 0x0774, 0x0773, 0x0773, + 0x0772, 0x0771, 0x0770, 0x0770, 0x076f, 0x076e, 0x076d, 0x076d, + 0x076c, 0x076b, 0x076a, 0x0770, 0x076f, 0x076e, 0x076d, 0x076d, + 0x076c, 0x076b, 0x076a, 0x076a, 0x0769, 0x0768, 0x0767, 0x0767, + 0x0766, 0x0765, 0x0764, 0x0764, 0x0763, 0x0762, 0x0761, 0x0761, + 0x0760, 0x075f, 0x075e, 0x075e, 0x075d, 0x075c, 0x075b, 0x075b, + 0x075a, 0x075a, 0x0759, 0x0759, 0x0758, 0x0757, 0x0756, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, + /* 0xff01 .. 0xffff */ + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, + 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x0120, 0x2a26, 0x2a26, + 0x30a1, 0x30aa, 0x30aa, 0x309d, 0x3196, 0x318c, 0x313a, 0x313b, + 0x313c, 0x313d, 0x313e, 0x3177, 0x3178, 0x3179, 0x3154, 0x318c, + 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3135, 0x3136, 0x3137, + 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, + 0x3140, 0x3142, 0x3143, 0x3144, 0x3145, 0x3145, 0x3145, 0x3145, + 0x3145, 0x3145, 0x3147, 0x3149, 0x314b, 0x314d, 0x314f, 0x314f, + 0x314f, 0x314f, 0x314f, 0x3150, 0x3151, 0x3152, 0x3152, 0x3152, + 0x3152, 0x3152, 0x3152, 0x3153, 0x3156, 0x30fb, 0x30fb, 0x31c4, + 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, + 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, + 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, + 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x3190, 0x0000, 0x0000, + 0x0000, 0x318d, 0x318d, 0x318d, 0x318d, 0x318d, 0x318d, 0x0000, + 0x0000, 0x318b, 0x318b, 0x318b, 0x318b, 0x318b, 0x318b, 0x0000, + 0x0000, 0x3189, 0x3189, 0x3189, 0x3189, 0x3189, 0x3189, 0x0000, + 0x0000, 0x3187, 0x3187, 0x3187, 0x0000, 0x0000, 0x0000, 0x00c2, + 0x00c2, 0x00ca, 0x00cc, 0x00c2, 0x00c0, 0x20c3, 0x0000, 0x251a, + 0x21a7, 0x21a7, 0x21a7, 0x21a7, 0x25b3, 0x25dd, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; diff --git a/dll/win32/kernel32/winnls/string/chartype.c b/dll/win32/kernel32/winnls/string/chartype.c new file mode 100644 index 00000000000..12ce9c85fb0 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/chartype.c @@ -0,0 +1,2154 @@ +/* Unicode ctype tables */ +/* Automatically generated; DO NOT EDIT!! */ + +#include "wine/unicode.h" + +const unsigned short wine_wctype_table[17152] = +{ + /* offsets */ + 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, + 0x0900, 0x0a00, 0x0b00, 0x0c00, 0x0d00, 0x0e00, 0x0f00, 0x1000, + 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1200, 0x1600, 0x1700, + 0x1800, 0x1900, 0x1a00, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00, + 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, + 0x2800, 0x2900, 0x2500, 0x2a00, 0x2b00, 0x2c00, 0x2d00, 0x2e00, + 0x2f00, 0x3000, 0x3100, 0x3200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x3300, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x3400, + 0x1200, 0x1200, 0x1200, 0x1200, 0x3500, 0x1200, 0x3600, 0x3700, + 0x3800, 0x3900, 0x3a00, 0x3b00, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x3c00, + 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, + 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, + 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, + 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, + 0x2800, 0x1200, 0x3d00, 0x3e00, 0x3f00, 0x4000, 0x4100, 0x4200, + /* values */ + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, + 0xe220, 0x9268, 0x8228, 0x9228, 0xa228, 0x8228, 0xe220, 0xe220, + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, + 0xe220, 0xe220, 0xe220, 0xe220, 0x8220, 0x8220, 0x8220, 0x9220, + 0xa248, 0xb210, 0xb210, 0x5210, 0x5210, 0x5210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0x4210, 0x7210, 0x4210, 0x7210, 0x7210, + 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, + 0x3284, 0x3284, 0x7210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0x1381, 0x1381, 0x1381, 0x1381, 0x1381, 0x1381, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0x1382, 0x1382, 0x1382, 0x1382, 0x1382, 0x1382, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0xb210, 0xb210, 0xb210, 0xb210, 0xe220, + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0x8228, 0xe220, 0xe220, + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, + 0x7248, 0xb210, 0x5210, 0x5210, 0x5210, 0x5210, 0xb210, 0xb210, + 0xb210, 0xb210, 0x1312, 0xb210, 0xb210, 0xe230, 0xb210, 0xb210, + 0x5210, 0x5210, 0x3214, 0x3214, 0xb210, 0x1312, 0xb210, 0xb210, + 0xb210, 0x3214, 0x1312, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0xb210, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0xb210, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, + 0x1302, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, + 0x1302, 0x1301, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, + 0x1302, 0x1301, 0x1301, 0x1301, 0x1302, 0x1302, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1302, 0x1301, 0x1301, 0x1302, 0x1301, 0x1301, + 0x1301, 0x1302, 0x1302, 0x1302, 0x1301, 0x1301, 0x1302, 0x1301, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, + 0x1302, 0x1301, 0x1302, 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, + 0x1302, 0x1301, 0x1301, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, + 0x1301, 0x1302, 0x1302, 0x1300, 0x1301, 0x1302, 0x1302, 0x1302, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1301, 0x1303, 0x1302, 0x1301, + 0x1303, 0x1302, 0x1301, 0x1303, 0x1302, 0x1301, 0x1302, 0x1301, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1302, 0x1301, 0x1303, 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1301, 0x1301, 0x1302, 0x1301, 0x1301, 0x1302, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, 0x1301, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1300, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0xb300, 0xb300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xb200, 0xb200, 0xb200, 0xb200, 0xb300, 0xb300, + 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, + 0x1300, 0x1300, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb300, 0xb200, 0x1300, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0x1301, 0x1302, 0x1301, 0x1302, 0xb300, 0xb200, 0x1301, 0x1302, + 0x0000, 0x0000, 0x1300, 0x1302, 0x1302, 0x1302, 0xb210, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xb200, 0xb200, 0x1301, 0xb210, + 0x1301, 0x1301, 0x1301, 0x0000, 0x1301, 0x0000, 0x1301, 0x1301, + 0x1302, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x0000, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1301, + 0x1302, 0x1302, 0x1301, 0x1301, 0x1301, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1301, 0x1302, 0xb200, 0x1301, + 0x1302, 0x1301, 0x1301, 0x1302, 0x1302, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x0000, + 0x0000, 0x1300, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x0000, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x0000, 0x1210, 0xb210, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x2210, 0xd200, + 0x2210, 0xd200, 0xd200, 0x2210, 0xd200, 0xd200, 0x2210, 0xd200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x2300, 0x2300, 0x2300, 0x2210, 0x2210, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x6220, 0x6220, 0x6220, 0x6220, 0x0000, 0x0000, 0xb200, 0xb200, + 0xc200, 0x5210, 0x5210, 0xc200, 0x7210, 0xc210, 0xb200, 0xb200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xc210, 0x0000, 0x0000, 0xc210, 0xc210, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0x6204, 0x6204, 0x6204, 0x6204, 0x6204, 0x6204, 0x6204, 0x6204, + 0x6204, 0x6204, 0x5210, 0x6210, 0x6210, 0xc210, 0xc300, 0xc300, + 0xd200, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc210, 0xc300, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x6220, 0xb200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xc300, 0xc300, 0xd200, + 0xd200, 0xb200, 0xd200, 0xd200, 0xd200, 0xd200, 0xc300, 0xc300, + 0x3204, 0x3204, 0x3204, 0x3204, 0x3204, 0x3204, 0x3204, 0x3204, + 0x3204, 0x3204, 0xc300, 0xc300, 0xc300, 0xc200, 0xc200, 0xc300, + 0xc210, 0xc210, 0xc210, 0xc210, 0xc210, 0xc210, 0xc210, 0xc210, + 0xc210, 0xc210, 0xc210, 0xc210, 0xc210, 0xc210, 0x0000, 0x6220, + 0xc300, 0xd200, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xc300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x2204, 0x2204, 0x2204, 0x2204, 0x2204, 0x2204, 0x2204, 0x2204, + 0x2204, 0x2204, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0x2300, 0x2300, 0xb200, 0xb210, + 0xb210, 0xb210, 0x2300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0xd200, 0xd200, + 0xd200, 0xd200, 0x2300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0x2300, 0xd200, 0xd200, 0xd200, + 0x2300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, + 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, + 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, 0x2210, 0x0000, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0x2210, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0x1200, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0x1200, 0xd200, 0x1300, 0x1200, 0x1200, + 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0x1200, 0x1200, + 0x1300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0x1210, 0x1210, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1210, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0xd200, 0x1200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x1300, + 0x1300, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0xd200, 0x1300, 0x1200, 0x1200, + 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0x1200, + 0x1200, 0x0000, 0x0000, 0x1200, 0x1200, 0xd200, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1300, 0x1300, 0x5200, 0x5200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x5200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xd200, 0xd200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, + 0x1300, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x0000, 0x0000, 0xd200, 0x0000, 0x1200, 0x1200, + 0x1200, 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, 0xd200, + 0xd200, 0x0000, 0x0000, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, + 0x0000, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0xd200, 0xd200, 0x1300, 0x1300, 0x1300, 0xd200, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xd200, 0xd200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, + 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0xd200, 0x1300, 0x1200, 0x1200, + 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0xd200, + 0xd200, 0x1200, 0x0000, 0x1200, 0x1200, 0xd200, 0x0000, 0x0000, + 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x0000, 0x5200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xd200, 0x1200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x1300, + 0x1300, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0xd200, 0x1300, 0x1200, 0xd200, + 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0x1200, + 0x1200, 0x0000, 0x0000, 0x1200, 0x1200, 0xd200, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd200, 0x1200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1200, 0x1300, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xd200, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, 0x0000, 0x1300, 0x1300, + 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x1200, 0x1200, + 0xd200, 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, 0x1200, 0x1200, + 0x1200, 0x0000, 0x1200, 0x1200, 0x1200, 0xd200, 0x0000, 0x0000, + 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1200, 0x1200, 0x1200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0x5200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1200, 0x1200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x1300, 0xd200, 0xd200, + 0xd200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, 0xd200, 0xd200, + 0xd200, 0x0000, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd200, 0xd200, 0x0000, + 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x1200, + 0x0000, 0x0000, 0x1200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0xd200, 0x1300, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, 0x1200, 0x1200, + 0x1200, 0x0000, 0x1200, 0x1200, 0xd200, 0xd200, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1200, 0x1200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, 0x0000, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x0000, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x1300, 0x1200, 0x1200, + 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x1200, 0x1200, + 0x1200, 0x0000, 0x1200, 0x1200, 0x1200, 0xd200, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, 0x0000, + 0x0000, 0x1200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x0000, 0x1200, 0x1200, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, 0x1200, + 0x1200, 0x1200, 0xd200, 0xd200, 0xd200, 0x0000, 0xd200, 0x0000, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1200, 0x1200, 0x1210, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0xd200, 0x1300, 0x1300, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, 0x5200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1210, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1210, 0x1210, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, 0x0000, 0x0000, 0x1300, + 0x1300, 0x0000, 0x1300, 0x0000, 0x0000, 0x1300, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x0000, 0x1300, + 0x0000, 0x0000, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0xd200, 0x1300, 0x1300, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0x0000, 0xd200, 0xd200, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x1300, 0x1300, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1200, 0x1200, 0x1200, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1210, 0x1210, 0x1210, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0xd200, 0xd200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0x1200, 0xd200, + 0x1200, 0xd200, 0xb210, 0xb210, 0xb210, 0xb210, 0x1200, 0x1200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0x0000, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1210, 0xd200, 0xd200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0x0000, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, 0x1200, 0x1200, + 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1210, 0x1210, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1200, 0x1200, 0xd200, 0xd200, 0xd200, + 0xd200, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0x1200, 0xd200, 0xd200, 0x1200, 0x1200, 0xd200, 0xd200, 0x1300, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1200, 0x1200, + 0xd200, 0xd200, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0xd200, + 0xd200, 0x1300, 0x1200, 0x1200, 0x1200, 0x1300, 0x1300, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1300, 0x1300, + 0x1300, 0xd200, 0xd200, 0xd200, 0xd200, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0x1200, 0x1200, 0xd200, 0xd200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0x1300, 0x1200, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1200, 0x1200, 0x1200, 0xd200, 0x1200, 0x1200, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1210, 0x1300, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0xd200, 0xd200, 0xd200, + 0x1200, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1210, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb210, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1210, 0x1210, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0xa208, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0xb210, 0xb210, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1210, 0x1210, 0x1210, 0x1300, 0x1300, + 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0xd200, 0x1210, 0x1210, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x1300, 0x1300, + 0x1300, 0x0000, 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1220, 0x1220, 0x1200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0x1200, + 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0x1210, 0x1210, 0x1210, 0x1300, + 0x1210, 0x1210, 0x1210, 0x5200, 0x1300, 0xd200, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xd200, 0xd200, 0xd200, 0xa208, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0xd200, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, + 0xd200, 0x1200, 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1200, 0x1200, 0xd200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0x0000, 0x0000, 0x0000, 0xb210, 0xb210, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1200, 0x0000, 0x0000, 0x0000, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, + 0xd200, 0x1200, 0x1200, 0x1200, 0x0000, 0x0000, 0x1210, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1200, 0xd200, 0x1200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, + 0xd200, 0x1200, 0xd200, 0x1200, 0x1200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, 0x0000, 0xd200, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1300, + 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0x1200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0x1200, 0xd200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0xd200, 0x1200, 0x1200, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1210, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0x1200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, 0x1200, + 0xd200, 0xd200, 0x1200, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0x1200, + 0xd200, 0xd200, 0x1200, 0x1200, 0x1200, 0xd200, 0x1200, 0xd200, + 0xd200, 0xd200, 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, 0x1200, 0xd200, 0xd200, + 0x0000, 0x0000, 0x0000, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1210, 0x1210, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0x1210, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0x1200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1300, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xd200, 0xd200, 0xd200, 0xd200, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, 0x0000, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x0000, 0x0000, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, 0x0000, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x0000, 0x0000, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x0000, 0x1301, 0x0000, 0x1301, 0x0000, 0x1301, 0x0000, 0x1301, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, 0x0000, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, 0x1303, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1303, 0xb200, 0x1302, 0xb200, + 0xb200, 0xb200, 0x1302, 0x1302, 0x1302, 0x0000, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1303, 0xb200, 0xb200, 0xb200, + 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, 0x0000, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x0000, 0xb200, 0xb200, 0xb200, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0xb200, 0xb200, 0xb200, + 0x0000, 0x0000, 0x1302, 0x1302, 0x1302, 0x0000, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1303, 0xb200, 0xb200, 0x0000, + 0xa208, 0xa208, 0xa208, 0xa208, 0xa208, 0xa208, 0xa208, 0xa208, + 0xa208, 0xa208, 0xa208, 0xe220, 0xe220, 0xe220, 0x1220, 0x2220, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xa208, 0x8208, 0xf220, 0xf220, 0xf220, 0xf220, 0xf220, 0x7208, + 0x5210, 0x5210, 0x5210, 0x5210, 0x5210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0x7200, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb200, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xa208, + 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, 0xe220, + 0x3200, 0x1302, 0x0000, 0x0000, 0x3200, 0x3200, 0x3200, 0x3200, + 0x3200, 0x3200, 0x4200, 0x4200, 0xb200, 0xb210, 0xb210, 0x1302, + 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, + 0x3200, 0x3200, 0x4200, 0x4200, 0xb200, 0xb210, 0xb210, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, + 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, + 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200, + 0x5200, 0x5200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0x1301, 0xb200, 0xb200, 0xb200, 0xb200, 0x1301, + 0xb200, 0xb200, 0x1302, 0x1301, 0x1301, 0x1301, 0x1302, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1302, 0xb200, 0x1301, 0xb200, 0xb200, + 0xb200, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x1301, 0xb200, 0x1301, 0xb200, + 0x1301, 0xb200, 0x1301, 0x1301, 0x1301, 0x1301, 0x5200, 0x1302, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1302, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1302, 0xb200, 0xb200, 0x1302, 0x1302, 0x1301, 0x1301, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x1301, 0x1302, 0x1302, + 0x1302, 0x1302, 0xb200, 0xb200, 0xb200, 0xb200, 0x1302, 0x1200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1301, 0x1302, 0x1300, 0x1300, 0x1300, + 0x1300, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0x4200, 0x5200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb210, 0xb210, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x1200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, + 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, 0x3200, + 0x3200, 0x3200, 0x3200, 0x3200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x1200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x0000, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb210, 0xb210, 0xb200, + 0xb200, 0xb200, 0xb200, 0x0000, 0xb200, 0x0000, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb210, 0xb210, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x0000, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, + 0x1301, 0x1302, 0x1301, 0x1301, 0x1301, 0x1302, 0x1302, 0x1301, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, 0x1301, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1300, 0x1301, 0x1301, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1302, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0x1301, 0x1302, 0x1301, 0x1302, 0xd200, + 0xd200, 0xd200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xb210, 0xb210, 0xb210, 0xb210, 0xb200, 0xb210, 0xb210, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, + 0x1210, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xd200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb300, + 0xb210, 0xb210, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0x0000, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, + 0xa248, 0xb210, 0xb210, 0xb210, 0xb200, 0x1300, 0x1300, 0x1300, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb200, 0xb200, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xb210, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xb200, 0xb200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xb210, 0xb200, 0xb200, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0xd200, 0xd200, 0xb200, 0xb200, 0x1300, 0x1300, 0x1300, + 0xb210, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0xb210, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xb200, 0xb200, 0x0000, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0xb200, 0xb200, 0xb200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x0000, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xb200, + 0xb200, 0xb200, 0xb200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xb200, 0xb200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0xb200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1210, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xb210, 0xb210, 0xb210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1300, 0xd200, + 0xd200, 0xd200, 0xd200, 0xb210, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xd200, 0xd200, 0xb210, 0xb300, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0xd200, 0xd200, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb300, + 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, 0xb300, + 0xb200, 0xb200, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1302, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1300, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1301, 0x1302, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0xb300, 0x1200, 0x1200, 0x1301, 0x1302, 0x1301, 0x1302, 0x0000, + 0x1301, 0x1302, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, 0x1301, 0x1302, + 0x1301, 0x1302, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1302, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0xd200, 0x1300, 0x1300, 0x1300, 0xd200, 0x1300, + 0x1300, 0x1300, 0x1300, 0xd200, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1200, 0x1200, 0xd200, 0xd200, 0x1200, + 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x5200, 0x5200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0xb210, 0xb210, 0xb210, 0xb210, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1200, 0x1200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1200, 0x1200, 0x1200, 0xd200, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1210, 0x1210, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1210, 0x1210, 0x1210, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1210, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0x1200, 0x1200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0x1200, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0xd200, 0x1200, 0x1200, 0xd200, 0xd200, + 0xd200, 0xd200, 0x1200, 0x1200, 0xd200, 0x1200, 0x1200, 0x1200, + 0x1200, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x0000, 0x1300, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x1210, 0x1210, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x1200, + 0x1200, 0xd200, 0xd200, 0x1200, 0x1200, 0xd200, 0xd200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0xd200, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0x1200, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x1210, 0x1210, 0x1210, 0x1210, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1200, + 0x1200, 0x1200, 0x1300, 0x1200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0xd200, 0x1300, 0xd200, 0xd200, 0xd200, 0x1300, 0x1300, 0xd200, + 0xd200, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0xd200, 0xd200, + 0x1300, 0xd200, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1210, 0x1210, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1200, 0x1200, 0xd200, 0x1200, 0x1200, + 0xd200, 0x1200, 0x1200, 0x1210, 0x1200, 0xd200, 0x0000, 0x0000, + 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, 0x1204, + 0x1204, 0x1204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2300, 0xd200, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x4200, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x0000, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x0000, 0x2300, 0x0000, + 0x2300, 0x2300, 0x0000, 0x2300, 0x2300, 0x0000, 0x2300, 0x2300, + 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, 0x2300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc200, 0xc200, 0xc200, 0xc200, 0xc200, 0xc200, + 0xc200, 0xc200, 0xc200, 0xc200, 0xc200, 0xc200, 0xc200, 0xc200, + 0xc200, 0xc200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xb210, 0xb210, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0x0000, 0x0000, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc200, 0xb200, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, + 0x7210, 0xb210, 0x7210, 0x0000, 0xb210, 0x7210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0x5210, + 0xb210, 0xb210, 0x4200, 0x4210, 0xb200, 0xb200, 0xb200, 0x0000, + 0xb210, 0x5200, 0x5210, 0xb210, 0x0000, 0x0000, 0x0000, 0x0000, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0x0000, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, + 0xc300, 0xc300, 0xc300, 0xc300, 0xc300, 0x0000, 0x0000, 0xe260, + 0x0000, 0xb210, 0xb210, 0x5210, 0x5200, 0x5210, 0xb210, 0xb210, + 0xb210, 0xb210, 0xb210, 0x4200, 0x7210, 0x4210, 0x7210, 0x7210, + 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, 0x3284, + 0x3284, 0x3284, 0x7210, 0xb210, 0xb200, 0xb200, 0xb200, 0xb210, + 0xb210, 0x1381, 0x1381, 0x1381, 0x1381, 0x1381, 0x1381, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, 0x1301, + 0x1301, 0x1301, 0x1301, 0xb210, 0xb210, 0xb210, 0xb200, 0xb210, + 0xb200, 0x1382, 0x1382, 0x1382, 0x1382, 0x1382, 0x1382, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, 0x1302, + 0x1302, 0x1302, 0x1302, 0xb210, 0xb200, 0xb210, 0xb200, 0xb210, + 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0xb210, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x0000, + 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, 0x1300, + 0x0000, 0x0000, 0x1300, 0x1300, 0x1300, 0x0000, 0x0000, 0x0000, + 0x5200, 0x5200, 0xb200, 0xb200, 0xb200, 0x5200, 0x5200, 0x0000, + 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0xb200, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xb220, 0xb220, 0xb220, 0xb200, 0xb200, 0x0000, 0x0000 +}; diff --git a/dll/win32/kernel32/winnls/string/collation.c b/dll/win32/kernel32/winnls/string/collation.c new file mode 100644 index 00000000000..465d740001b --- /dev/null +++ b/dll/win32/kernel32/winnls/string/collation.c @@ -0,0 +1,1657 @@ +/* Unicode collation element table */ +/* generated from http://www.unicode.org/reports/tr10/allkeys.txt */ +/* DO NOT EDIT!! */ + +const unsigned int collation_table[12800] = +{ + /* index */ + 0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000800, 0x00000900, + 0x00000100, 0x00000a00, 0x00000b00, 0x00000c00, 0x00000d00, 0x00000e00, 0x00000f00, 0x00001000, + 0x00001100, 0x00001200, 0x00001300, 0x00001400, 0x00001500, 0x00001600, 0x00001700, 0x00001800, + 0x00001900, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00001a00, 0x00001b00, + 0x00001c00, 0x00001d00, 0x00001e00, 0x00001f00, 0x00002000, 0x00002100, 0x00002200, 0x00002300, + 0x00002400, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00002500, 0x00002600, + 0x00002700, 0x00002800, 0x00002900, 0x00002a00, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, + 0x00000100, 0x00002b00, 0x00002c00, 0x00002d00, 0x00002e00, 0x00002f00, 0x00003000, 0x00003100, + /* defaults */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0000 .. 0x00ff */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x02010111, 0x02020111, 0x02030111, 0x02040111, 0x02050111, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02090111, 0x024b0111, 0x02700111, 0x02a90111, 0x09e00111, 0x02aa0111, 0x02a70111, 0x02690111, + 0x027a0111, 0x027b0111, 0x02a20111, 0x039f0111, 0x022d0111, 0x02210111, 0x02550111, 0x02a40111, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x02370111, 0x02350111, 0x03a30111, 0x03a40111, 0x03a50111, 0x024e0111, + 0x02a10111, 0x0a150151, 0x0a290141, 0x0a3d0151, 0x0a490151, 0x0a650151, 0x0a910151, 0x0a990151, + 0x0ab90151, 0x0ad30161, 0x0ae70141, 0x0af70141, 0x0b030161, 0x0b2b0151, 0x0b330151, 0x0b4b0161, + 0x0b670141, 0x0b730141, 0x0b7f0141, 0x0ba70151, 0x0bbf0151, 0x0bd70141, 0x0bef0151, 0x0bfb0141, + 0x0c030151, 0x0c070141, 0x0c130141, 0x027c0111, 0x02a60111, 0x027d0111, 0x020f0111, 0x021b0111, + 0x020c0111, 0x0a150111, 0x0a290111, 0x0a3d0111, 0x0a490111, 0x0a650111, 0x0a910111, 0x0a990111, + 0x0ab90111, 0x0ad30111, 0x0ae70111, 0x0af70111, 0x0b030111, 0x0b2b0111, 0x0b330111, 0x0b4b0111, + 0x0b670111, 0x0b730111, 0x0b7f0111, 0x0ba70111, 0x0bbf0111, 0x0bd70111, 0x0bef0111, 0x0bfb0111, + 0x0c030111, 0x0c070111, 0x0c130111, 0x027e0111, 0x03a70111, 0x027f0111, 0x03aa0111, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02060111, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02090141, 0x024c0111, 0x09df0111, 0x09e10111, 0x09de0111, 0x09e20111, 0x03a80111, 0x029c0111, + 0x02140111, 0x029f0111, 0x0a150181, 0x02780111, 0x03a60111, 0x02200111, 0x02a00111, 0x02100111, + 0x030a0111, 0x03a00111, 0x0a0d0151, 0x0a0e0151, 0x020d0111, 0x0c9f0121, 0x029d0111, 0x025f0111, + 0x02190111, 0x0a0c0151, 0x0b4b01a1, 0x02790111, 0x0a0c0171, 0x0a0c0171, 0x0a0e0171, 0x024f0111, + 0x0a150151, 0x0a150151, 0x0a150151, 0x0a150151, 0x0a150151, 0x0a150151, 0x0a190121, 0x0a3d0151, + 0x0a650151, 0x0a650151, 0x0a650151, 0x0a650151, 0x0ad30161, 0x0ad30161, 0x0ad30161, 0x0ad30161, + 0x0a5d0121, 0x0b330151, 0x0b4b0161, 0x0b4b0161, 0x0b4b0161, 0x0b4b0161, 0x0b4b0161, 0x03a20111, + 0x0b530121, 0x0bd70141, 0x0bd70141, 0x0bd70141, 0x0bd70141, 0x0c070141, 0x0c3b0121, 0x0ba70131, + 0x0a150111, 0x0a150111, 0x0a150111, 0x0a150111, 0x0a150111, 0x0a150111, 0x0a190111, 0x0a3d0111, + 0x0a650111, 0x0a650111, 0x0a650111, 0x0a650111, 0x0ad30111, 0x0ad30111, 0x0ad30111, 0x0ad30111, + 0x0a5d0111, 0x0b330111, 0x0b4b0111, 0x0b4b0111, 0x0b4b0111, 0x0b4b0111, 0x0b4b0111, 0x03a10111, + 0x0b530111, 0x0bd70111, 0x0bd70111, 0x0bd70111, 0x0bd70111, 0x0c070111, 0x0c3b0111, 0x0c070111, + /* 0x0100 .. 0x01ff */ + 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a3d0151, 0x0a3d0111, + 0x0a3d0151, 0x0a3d0111, 0x0a3d0151, 0x0a3d0111, 0x0a3d0151, 0x0a3d0111, 0x0a490151, 0x0a490111, + 0x0a4d0121, 0x0a4d0111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, + 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a990151, 0x0a990111, 0x0a990151, 0x0a990111, + 0x0a990151, 0x0a990111, 0x0a990151, 0x0a990111, 0x0ab90151, 0x0ab90111, 0x0ac50131, 0x0ac50111, + 0x0ad30161, 0x0ad30111, 0x0ad30161, 0x0ad30111, 0x0ad30161, 0x0ad30111, 0x0ad30161, 0x0ad30111, + 0x0ad30161, 0x0ad70111, 0x0ad30181, 0x0ad30131, 0x0ae70141, 0x0ae70111, 0x0af70141, 0x0af70111, + 0x0b7b0111, 0x0b030161, 0x0b030111, 0x0b030161, 0x0b030111, 0x0b030161, 0x0b030111, 0x0b030181, + 0x0b030131, 0x0b0b0121, 0x0b0b0111, 0x0b330151, 0x0b330111, 0x0b330151, 0x0b330111, 0x0b330151, + 0x0b330111, 0x0c580121, 0x0b470121, 0x0b470111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b4b0161, 0x0b4b0111, 0x0b4b0181, 0x0b4b0131, 0x0b7f0141, 0x0b7f0111, 0x0b7f0141, 0x0b7f0111, + 0x0b7f0141, 0x0b7f0111, 0x0ba70151, 0x0ba70111, 0x0ba70151, 0x0ba70111, 0x0ba70151, 0x0ba70111, + 0x0ba70151, 0x0ba70111, 0x0bbf0151, 0x0bbf0111, 0x0bbf0151, 0x0bbf0111, 0x0bc30121, 0x0bc30111, + 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, + 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bfb0141, 0x0bfb0111, 0x0c070141, 0x0c070111, + 0x0c070141, 0x0c130141, 0x0c130111, 0x0c130141, 0x0c130111, 0x0c130141, 0x0c130111, 0x0ba70131, + 0x0a310111, 0x0a350121, 0x0a390121, 0x0a390111, 0x0c4f0121, 0x0c4f0111, 0x0b570121, 0x0a410121, + 0x0a410111, 0x0a510121, 0x0a550121, 0x0a590121, 0x0a590111, 0x0a610111, 0x0a690121, 0x0a6d0121, + 0x0a710121, 0x0a950121, 0x0a950111, 0x0aa50121, 0x0aad0121, 0x0ac10111, 0x0ae30121, 0x0adf0121, + 0x0afb0121, 0x0afb0111, 0x0b0f0111, 0x0b230111, 0x0be30121, 0x0b3b0121, 0x0b3f0111, 0x0b5b0121, + 0x0b4b0161, 0x0b4b0111, 0x0ab50121, 0x0ab50111, 0x0b6b0121, 0x0b6b0111, 0x0b830121, 0x0c470121, + 0x0c470111, 0x0baf0121, 0x0bb30111, 0x0bc70111, 0x0bcb0121, 0x0bcb0111, 0x0bcf0121, 0x0bd70141, + 0x0bd70111, 0x0beb0121, 0x0bf30121, 0x0c0f0121, 0x0c0f0111, 0x0c170121, 0x0c170111, 0x0c270121, + 0x0c2b0121, 0x0c2b0111, 0x0c2f0111, 0x0c430111, 0x0c4b0121, 0x0c4b0111, 0x0c610111, 0x0c3f0111, + 0x0c710111, 0x0c750111, 0x0c790111, 0x0c7d0111, 0x0a490171, 0x0a490171, 0x0a490131, 0x0b030181, + 0x0b030181, 0x0b030131, 0x0b330171, 0x0b330171, 0x0b330131, 0x0a150151, 0x0a150111, 0x0ad30161, + 0x0ad30111, 0x0b4b0161, 0x0b4b0111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, + 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0a690111, 0x0a150151, 0x0a150111, + 0x0a150151, 0x0a150111, 0x0a190121, 0x0a190111, 0x0aa10121, 0x0aa10111, 0x0a990151, 0x0a990111, + 0x0af70141, 0x0af70111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0c270121, 0x0c270111, + 0x0ae70111, 0x0a490171, 0x0a490171, 0x0a490131, 0x0a990151, 0x0a990111, 0x0ac10121, 0x0c3f0121, + 0x0b330151, 0x0b330111, 0x0a150151, 0x0a150111, 0x0a190121, 0x0a190111, 0x0b530121, 0x0b530111, + /* 0x0200 .. 0x02ff */ + 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, + 0x0ad30161, 0x0ad30111, 0x0ad30161, 0x0ad30111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b7f0141, 0x0b7f0111, 0x0b7f0141, 0x0b7f0111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, + 0x0ba70151, 0x0ba70111, 0x0bbf0151, 0x0bbf0111, 0x0c370121, 0x0c370111, 0x0ab90151, 0x0ab90111, + 0xffffffff, 0xffffffff, 0x0b630121, 0x0b630111, 0x0c1b0121, 0x0c1b0111, 0x0a150151, 0x0a150111, + 0x0a650151, 0x0a650111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b4b0161, 0x0b4b0111, 0x0c070141, 0x0c070111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a1d0111, 0x0a210111, 0x0a250111, 0x0a350111, 0x0b570111, 0x0a450111, 0x0a510111, 0x0a550111, + 0x0a750111, 0x0a6d0111, 0x0a790111, 0x0a710111, 0x0a7d0111, 0x0a810111, 0x0a850111, 0x0aef0111, + 0x0aa50111, 0x0ab10111, 0x0a9d0111, 0x0aad0111, 0x0a8d0111, 0x0bdf0111, 0x0ac90111, 0x0acd0111, + 0x0adf0111, 0x0ae30111, 0x0adb0111, 0x0b130111, 0x0b170111, 0x0b1b0111, 0x0b1f0111, 0x0be30111, + 0x0be70111, 0x0b2f0111, 0x0b3b0111, 0x0b430111, 0x0b370111, 0x0b5b0111, 0x0b4f0111, 0x0b5f0111, + 0x0b6f0111, 0x0b870111, 0x0b8b0111, 0x0b8f0111, 0x0b930111, 0x0b970111, 0x0b9b0111, 0x0b9f0111, + 0x0b830111, 0x0ba30111, 0x0bab0111, 0x0baf0111, 0x0af30111, 0x0bb70111, 0x0bbb0111, 0x0bd30111, + 0x0bcf0111, 0x0bdb0111, 0x0beb0111, 0x0bf30111, 0x0bf70111, 0x0bff0111, 0x0b270111, 0x0c0b0111, + 0x0c1f0111, 0x0c230111, 0x0c270111, 0x0c330111, 0x0c530111, 0x0c5b0111, 0x0c6d0111, 0x0c810111, + 0x0c850111, 0x0a2d0111, 0x0a890111, 0x0aa90111, 0x0abd0111, 0x0aeb0111, 0x0aff0111, 0x0b070111, + 0x0b770111, 0x0c650111, 0x0c690111, 0x0a490131, 0x0a490131, 0x0a490131, 0x0bbf0131, 0x0bbf0131, + 0x0bbf0131, 0x0a910131, 0x0b030131, 0x0b030131, 0x0c890111, 0x0c8d0111, 0xffffffff, 0xffffffff, + 0x0ab90191, 0x0ac90121, 0x0ae70171, 0x0b7f0191, 0x0b870121, 0x0b8f0121, 0x0ba30121, 0x0bfb0171, + 0x0c070171, 0x02e90111, 0x02eb0111, 0x0ad10111, 0x0c580111, 0x0ad20111, 0x0c5a0111, 0x0c5f0111, + 0x0c570111, 0x0c600111, 0x02ec0111, 0x02ed0111, 0x02ee0111, 0x02ef0111, 0x02f00111, 0x02f10111, + 0x02f20111, 0x02f30111, 0x02f40111, 0x02f50111, 0x02f60111, 0x02f70111, 0x02f80111, 0x02f90111, + 0x09d30111, 0x09d40111, 0x02fa0111, 0x02fb0111, 0x02fc0111, 0x02fd0111, 0x02fe0111, 0x02ff0111, + 0x02120111, 0x02130111, 0x02150111, 0x021a0111, 0x020e0111, 0x02160111, 0x03000111, 0xffffffff, + 0x0aad0131, 0x0b0301b1, 0x0ba70181, 0x0c030191, 0x0c5b0121, 0x03010111, 0x03020111, 0x03030111, + 0x03040111, 0x03050111, 0x03060111, 0x03070111, 0x03080111, 0x03090111, 0x0c590111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0300 .. 0x03ff */ + 0x00000611, 0x00000511, 0x00000811, 0x00000e11, 0x00001311, 0x00001411, 0x00000711, 0x00000f11, + 0x00000c11, 0x00001511, 0x00000a11, 0x00000d11, 0x00000911, 0x00001611, 0x00001711, 0x00001811, + 0x00001911, 0x00001a11, 0x00001b11, 0x00000311, 0x00000411, 0x00001c11, 0x00001d11, 0x00001e11, + 0x00001f11, 0x00002011, 0x00002111, 0x00002211, 0x00002311, 0x00002411, 0x00002511, 0x00002611, + 0x00002711, 0x00002811, 0x00002911, 0x00002a11, 0x00002b11, 0x00002c11, 0x00002d11, 0x00001111, + 0x00001211, 0x00002e11, 0x00002f11, 0x00003011, 0x00003111, 0x00003211, 0x00003311, 0x00003411, + 0x00003511, 0x00003611, 0x00000211, 0x00003711, 0x00003811, 0x00003911, 0x00003a11, 0x00003b11, + 0x00001011, 0x00003c11, 0x00003d11, 0x00003e11, 0x00003f11, 0x00004011, 0x00004111, 0x00004211, + 0x00000611, 0x00000511, 0x00000b11, 0x00000311, 0x00000c11, 0x00004311, 0x00004411, 0x00004511, + 0x00004611, 0x00004711, 0x00004811, 0x00004911, 0x00004a11, 0x00004b11, 0x00004c11, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00004d11, 0x00004e11, 0x00004f11, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x02e90111, 0x02ea0111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x0c9b0111, 0xffffffff, 0xffffffff, 0xffffffff, 0x02350111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x020d0111, 0x02140111, 0x0c910121, 0x025f0111, + 0x0c950131, 0x0c990121, 0x0c9b0121, 0xffffffff, 0x0ca20121, 0xffffffff, 0x0ca80121, 0x0cac0121, + 0x0c9b0111, 0x0c910121, 0x0c920131, 0x0c930121, 0x0c940121, 0x0c950131, 0x0c980121, 0x0c990121, + 0x0c9a0131, 0x0c9b0121, 0x0c9d0131, 0x0c9e0121, 0x0c9f0131, 0x0ca00121, 0x0ca10121, 0x0ca20121, + 0x0ca30131, 0x0ca50131, 0xffffffff, 0x0ca60131, 0x0ca70121, 0x0ca80121, 0x0ca90131, 0x0caa0121, + 0x0cab0121, 0x0cac0121, 0x0c9b0121, 0x0ca80121, 0x0c910111, 0x0c950111, 0x0c990111, 0x0c9b0111, + 0x0ca80111, 0x0c910111, 0x0c920111, 0x0c930111, 0x0c940111, 0x0c950111, 0x0c980111, 0x0c990111, + 0x0c9a0111, 0x0c9b0111, 0x0c9d0111, 0x0c9e0111, 0x0c9f0111, 0x0ca00111, 0x0ca10111, 0x0ca20111, + 0x0ca30111, 0x0ca50111, 0x0ca60141, 0x0ca60111, 0x0ca70111, 0x0ca80111, 0x0ca90111, 0x0caa0111, + 0x0cab0111, 0x0cac0111, 0x0c9b0111, 0x0ca80111, 0x0ca20111, 0x0ca80111, 0x0cac0111, 0xffffffff, + 0x0c920121, 0x0c9a0121, 0x0ca80131, 0x0ca80131, 0x0ca80131, 0x0ca90121, 0x0ca30121, 0x0c9d0121, + 0xffffffff, 0xffffffff, 0x0c970121, 0x0c970111, 0x0c960121, 0x0c960111, 0x0ca40121, 0x0ca40111, + 0x0cad0121, 0x0cad0111, 0x0cae0121, 0x0cae0111, 0x0caf0121, 0x0caf0111, 0x0cb00121, 0x0cb00111, + 0x0cb10121, 0x0cb10111, 0x0cb20121, 0x0cb20111, 0x0cb30121, 0x0cb30111, 0x0cb40121, 0x0cb40111, + 0x0c9d0121, 0x0ca50121, 0x0ca60121, 0x0c9c0111, 0x0c9a0141, 0x0c950121, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0400 .. 0x04ff */ + 0x0cf10121, 0x0cf10121, 0x0ce50121, 0x0ce90121, 0x0cf90121, 0x0d110121, 0x0d210121, 0x0d250121, + 0x0d2d0121, 0x0d4d0121, 0x0d650121, 0x0d9d0121, 0x0da10121, 0x0d190121, 0x0da90121, 0x0e050121, + 0x0cb50121, 0x0ccd0121, 0x0cd10121, 0x0cd50131, 0x0ce10121, 0x0cf10121, 0x0cfd0121, 0x0d090121, + 0x0d190121, 0x0d290121, 0x0d310121, 0x0d490121, 0x0d510121, 0x0d550121, 0x0d690121, 0x0d790121, + 0x0d850121, 0x0d8d0121, 0x0d950121, 0x0da50121, 0x0dc10121, 0x0dc50121, 0x0de10121, 0x0de90121, + 0x0e090121, 0x0e0d0121, 0x0e110121, 0x0e150121, 0x0e1d0121, 0x0e290121, 0x0e310121, 0x0e350121, + 0x0cb50111, 0x0ccd0111, 0x0cd10111, 0x0cd50111, 0x0ce10111, 0x0cf10111, 0x0cfd0111, 0x0d090111, + 0x0d190111, 0x0d290111, 0x0d310111, 0x0d490111, 0x0d510111, 0x0d550111, 0x0d690111, 0x0d790111, + 0x0d850111, 0x0d8d0111, 0x0d950111, 0x0da50111, 0x0dc10111, 0x0dc50111, 0x0de10111, 0x0de90111, + 0x0e090111, 0x0e0d0111, 0x0e110111, 0x0e150111, 0x0e1d0111, 0x0e290111, 0x0e310111, 0x0e350111, + 0x0cf10111, 0x0cf10111, 0x0ce50111, 0x0ce90111, 0x0cf90111, 0x0d110111, 0x0d210111, 0x0d250111, + 0x0d2d0111, 0x0d4d0111, 0x0d650111, 0x0d9d0111, 0x0da10111, 0x0d190111, 0x0da90111, 0x0e050111, + 0x0dd10121, 0x0dd10111, 0x0e250121, 0x0e250111, 0x0e390121, 0x0e390111, 0x0e3d0121, 0x0e3d0111, + 0x0e450121, 0x0e450111, 0x0e410121, 0x0e410111, 0x0e490121, 0x0e490111, 0x0e4d0121, 0x0e4d0111, + 0x0e510121, 0x0e510111, 0x0e550121, 0x0e550111, 0x0e590121, 0x0e590111, 0x0e5d0121, 0x0e5d0111, + 0x0dbd0121, 0x0dbd0111, 0x0ddd0121, 0x0ddd0111, 0x0dd90121, 0x0dd90111, 0x0dd50121, 0x0dd50111, + 0x0d810121, 0x0d810111, 0x030b0111, 0x00005411, 0x00005511, 0x00005611, 0x00005711, 0xffffffff, + 0x00000001, 0x00000001, 0xffffffff, 0xffffffff, 0x0e210121, 0x0e210111, 0x0d890121, 0x0d890111, + 0x0cd50141, 0x0cd50121, 0x0cd90121, 0x0cd90111, 0x0cdd0121, 0x0cdd0111, 0x0d050121, 0x0d050111, + 0x0ced0121, 0x0ced0111, 0x0d350121, 0x0d350111, 0x0d450121, 0x0d450111, 0x0d410121, 0x0d410111, + 0x0d3d0121, 0x0d3d0111, 0x0d590121, 0x0d590111, 0x0d610121, 0x0d610111, 0x0d7d0121, 0x0d7d0111, + 0x0e610121, 0x0e610111, 0x0d910121, 0x0d910111, 0x0d990121, 0x0d990111, 0x0db50121, 0x0db50111, + 0x0db90121, 0x0db90111, 0x0dc90121, 0x0dc90111, 0x0de50121, 0x0de50111, 0x0df10121, 0x0df10111, + 0x0df90121, 0x0df90111, 0x0dcd0121, 0x0dcd0111, 0x0dfd0121, 0x0dfd0111, 0x0e010121, 0x0e010111, + 0x0e650111, 0x0cfd0121, 0x0cfd0111, 0x0d390121, 0x0d390111, 0xffffffff, 0xffffffff, 0x0d5d0121, + 0x0d5d0111, 0xffffffff, 0xffffffff, 0x0df50121, 0x0df50111, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0cb90121, 0x0cb90111, 0x0cbd0121, 0x0cbd0111, 0x0cc90121, 0x0cc90111, 0x0cf50121, 0x0cf50111, + 0x0cc10121, 0x0cc10111, 0x0cc50121, 0x0cc50111, 0x0d010121, 0x0d010111, 0x0d0d0121, 0x0d0d0111, + 0x0d150121, 0x0d150111, 0x0d190121, 0x0d190111, 0x0d1d0121, 0x0d1d0111, 0x0d6d0121, 0x0d6d0111, + 0x0d710121, 0x0d710111, 0x0d750121, 0x0d750111, 0x0e2d0121, 0x0e2d0111, 0x0da50121, 0x0da50111, + 0x0dad0121, 0x0dad0111, 0x0db10121, 0x0db10111, 0x0ded0121, 0x0ded0111, 0xffffffff, 0xffffffff, + 0x0e190121, 0x0e190111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0500 .. 0x05ff */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x0e900121, 0x0e910121, 0x0e920121, 0x0e930121, 0x0e940131, 0x0e950121, 0x0e960121, + 0x0e970121, 0x0e980121, 0x0e990121, 0x0e9a0121, 0x0e9b0121, 0x0e9c0121, 0x0e9d0121, 0x0e9e0121, + 0x0e9f0121, 0x0ea00121, 0x0ea10121, 0x0ea20121, 0x0ea30131, 0x0ea40121, 0x0ea50121, 0x0ea60121, + 0x0ea70121, 0x0ea80121, 0x0ea90121, 0x0eaa0121, 0x0eab0121, 0x0eac0121, 0x0ead0131, 0x0eae0121, + 0x0eaf0121, 0x0eb00121, 0x0eb10121, 0x0eb20121, 0x0eb30121, 0x0eb40121, 0x0eb50121, 0xffffffff, + 0xffffffff, 0x0eb60111, 0x02bf0111, 0x02c00111, 0x024d0111, 0x022e0111, 0x02500111, 0x02c10111, + 0xffffffff, 0x0e900111, 0x0e910111, 0x0e920111, 0x0e930111, 0x0e940111, 0x0e950111, 0x0e960111, + 0x0e970111, 0x0e980111, 0x0e990111, 0x0e9a0111, 0x0e9b0111, 0x0e9c0111, 0x0e9d0111, 0x0e9e0111, + 0x0e9f0111, 0x0ea00111, 0x0ea10111, 0x0ea20111, 0x0ea30111, 0x0ea40111, 0x0ea50111, 0x0ea60111, + 0x0ea70111, 0x0ea80111, 0x0ea90111, 0x0eaa0111, 0x0eab0111, 0x0eac0111, 0x0ead0111, 0x0eae0111, + 0x0eaf0111, 0x0eb00111, 0x0eb10111, 0x0eb20111, 0x0eb30111, 0x0eb40111, 0x0eb50111, 0x0e940121, + 0xffffffff, 0x02380111, 0x02220111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0xffffffff, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00005811, 0x00005911, 0x00005a11, 0x00005b11, 0x00005c11, 0x00005d11, 0x00005e11, 0x00005f11, + 0x00006011, 0x00006111, 0xffffffff, 0x00006211, 0x00006311, 0x00000001, 0x02c20111, 0x00006411, + 0x02c30111, 0x00006511, 0x00006611, 0x02c40111, 0x00000001, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0eb70111, 0x0eb80111, 0x0eb90111, 0x0eba0111, 0x0ebb0111, 0x0ebc0111, 0x0ebd0111, 0x0ebe0111, + 0x0ebf0111, 0x0ec00111, 0x0ec10131, 0x0ec10111, 0x0ec20111, 0x0ec30131, 0x0ec30111, 0x0ec40121, + 0x0ec40111, 0x0ec50111, 0x0ec60111, 0x0ec70121, 0x0ec70111, 0x0ec80121, 0x0ec80111, 0x0ec90111, + 0x0eca0111, 0x0ecb0111, 0x0ecc0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0ebc0121, 0x0ebc0121, 0x0ec00121, 0x02c50111, 0x02c60111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0600 .. 0x06ff */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x022f0111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x02360111, 0xffffffff, 0xffffffff, 0xffffffff, 0x02510111, + 0xffffffff, 0x0ecd0111, 0x0ece0111, 0x0ecf0111, 0x0ed20111, 0x0ed30111, 0x0ed50111, 0x0ed60111, + 0x0ed70111, 0x0edb0111, 0x0edc0111, 0x0edd0111, 0x0ee30111, 0x0ee90111, 0x0eea0111, 0x0eee0111, + 0x0eef0111, 0x0ef90111, 0x0efa0111, 0x0f040111, 0x0f050111, 0x0f0a0111, 0x0f0b0111, 0x0f0f0111, + 0x0f100111, 0x0f120111, 0x0f130111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x020b0111, 0x0f160111, 0x0f1d0111, 0x0f200111, 0x0f2d0111, 0x0f320111, 0x0f330111, 0x0f390111, + 0x0f3e0111, 0x0f480111, 0x0f490111, 0x00006811, 0x00006911, 0x00006a11, 0x00006b11, 0x00006c11, + 0x00006d11, 0x00006e11, 0x00006f11, 0x00007011, 0x00007111, 0x00007211, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x02ab0111, 0x02300111, 0x02310111, 0x02a30111, 0xffffffff, 0xffffffff, + 0x00007311, 0x0ed10111, 0x0ed00111, 0x0ed40111, 0x0ecd0111, 0x0ed60121, 0x0f3e0121, 0x0f420121, + 0x0f490121, 0x0ede0111, 0x0edf0111, 0x0ed80111, 0x0ee00111, 0x0ee10111, 0x0ed90111, 0x0ee20111, + 0x0eda0111, 0x0eeb0111, 0x0eec0111, 0x0ee40111, 0x0ee50111, 0x0eed0111, 0x0ee60111, 0x0ee80111, + 0x0ef00111, 0x0ef10111, 0x0ef20111, 0x0ef30111, 0x0ef40111, 0x0ef50111, 0x0ef60111, 0x0ef70111, + 0x0ef80111, 0x0efb0111, 0x0efc0111, 0x0efd0111, 0x0efe0111, 0x0eff0111, 0x0f000111, 0x0f010111, + 0x0f020111, 0x0f030111, 0x0f060111, 0x0f070111, 0x0f080111, 0x0f0c0111, 0x0f0d0111, 0x0f110111, + 0x0f140111, 0x0f170111, 0x0f180111, 0x0f190111, 0x0f1a0111, 0x0f1b0111, 0x0f1c0111, 0x0f1e0111, + 0x0f1f0111, 0x0f210111, 0x0f220111, 0x0f230111, 0x0f240111, 0x0f250111, 0x0f260111, 0x0f270111, + 0x0f280111, 0x0f290111, 0x0f2a0111, 0x0f2b0111, 0x0f2c0111, 0x0f2e0111, 0x0f2f0111, 0x0f300111, + 0x0f310111, 0x0f380111, 0x0f340111, 0x0f350111, 0x0f360111, 0x0f370111, 0x0f3a0111, 0x0ee70111, + 0x0f3d0111, 0x0f3b0111, 0x0f3b0111, 0x0f3c0111, 0x0f3f0111, 0x0f400111, 0x0f410111, 0x0f420111, + 0x0f430111, 0x0f440111, 0x0f450111, 0x0f460111, 0x0f4a0111, 0x0f4b0111, 0x0f4c0111, 0x0f470111, + 0x0f4d0111, 0x0f4e0111, 0x0f4f0111, 0x0f4f0111, 0x02570111, 0x0f3d0111, 0x00007411, 0x00007511, + 0x00007611, 0x00007711, 0x00007811, 0x00007911, 0x00007a11, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00007b11, 0x00007c11, 0x00007d11, 0x00007e11, 0x0f3e0121, 0x0f490121, 0x00007f11, + 0x00008011, 0x030c0111, 0x00000001, 0x00000001, 0x00000001, 0x00008111, 0xffffffff, 0xffffffff, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x0f090111, 0x0f0e0111, 0x0f150111, 0x0ecd0121, 0x0f320121, 0xffffffff, + /* 0x0700 .. 0x07ff */ + 0x02660111, 0x02580111, 0x02590111, 0x02390111, 0x023a0111, 0x023b0111, 0x023c0111, 0x023d0111, + 0x023e0111, 0x02520111, 0x02c70111, 0x02c80111, 0x02c90111, 0x02ca0111, 0xffffffff, 0x00000000, + 0x0f500111, 0x00008211, 0x0f510111, 0x0f520111, 0x0f520121, 0x0f530111, 0x0f540111, 0x0f550111, + 0x0f560111, 0x0f570111, 0x0f580111, 0x0f590111, 0x0f590121, 0x0f5a0111, 0x0f5b0111, 0x0f5c0111, + 0x0f5d0111, 0x0f5e0111, 0x0f5f0111, 0x0f600111, 0x0f600121, 0x0f610111, 0x0f620111, 0x0f620121, + 0x0f630111, 0x0f640111, 0x0f650111, 0x0f660111, 0x0f670111, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00008311, 0x00008411, 0x00008511, 0x00008611, 0x00008711, 0x00008811, 0x00008911, 0x00008a11, + 0x00008b11, 0x00008c11, 0x00008d11, 0x00008e11, 0x00008f11, 0x00009011, 0x00009111, 0x00009211, + 0x00009311, 0x00009411, 0x00009511, 0x00009611, 0x00009711, 0x00009811, 0x00009911, 0x00009a11, + 0x00009b11, 0x00009c11, 0x00009d11, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0f680111, 0x0f6b0111, 0x0f6c0111, 0x0f6d0111, 0x0f6f0111, 0x0f700111, 0x0f710111, 0x0f720111, + 0x0f750111, 0x0f770111, 0x0f780111, 0x0f790111, 0x0f7b0111, 0x0f7f0111, 0x0f800111, 0x0f820111, + 0x0f830111, 0x0f870111, 0x0f880111, 0x0f890111, 0x0f8a0111, 0x0f8b0111, 0x0f8c0111, 0x0f8d0111, + 0x0f7c0111, 0x0f690111, 0x0f6a0111, 0x0f7a0111, 0x0f6e0111, 0x0f840111, 0x0f850111, 0x0f860111, + 0x0f7d0111, 0x0f7e0111, 0x0f730111, 0x0f740111, 0x0f810111, 0x0f760111, 0x0f8e0111, 0x0f8f0111, + 0x0f900111, 0x0f910111, 0x0f920111, 0x0f930111, 0x0f940111, 0x0f950111, 0x0f960111, 0x0f970111, + 0x0f980111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0900 .. 0x09ff */ + 0xffffffff, 0x00009f11, 0x0000a011, 0x0000a111, 0xffffffff, 0x10d70111, 0x10d80111, 0x10d90111, + 0x10da0111, 0x10db0111, 0x10dc0111, 0x10dd0111, 0x10df0111, 0x10e10111, 0x10e20111, 0x10e30111, + 0x10e40111, 0x10e50111, 0x10e60111, 0x10e70111, 0x10e80111, 0x10e90111, 0x10ea0111, 0x10eb0111, + 0x10ec0111, 0x10ed0111, 0x10ee0111, 0x10ef0111, 0x10f00111, 0x10f10111, 0x10f20111, 0x10f30111, + 0x10f40111, 0x10f50111, 0x10f60111, 0x10f70111, 0x10f80111, 0x10f90111, 0x10fa0111, 0x10fb0111, + 0x10fc0111, 0x10fc0111, 0x10fd0111, 0x10fe0111, 0x10ff0111, 0x11000111, 0x11010111, 0x11020111, + 0x11030111, 0x11030111, 0x11040111, 0x11050111, 0x11050111, 0x11060111, 0x11070111, 0x11080111, + 0x11090111, 0x110a0111, 0xffffffff, 0xffffffff, 0x00009e11, 0x110b0111, 0x110c0111, 0x110d0111, + 0x110e0111, 0x110f0111, 0x11100111, 0x11110111, 0x11120111, 0x11150111, 0x11160111, 0x11170111, + 0x11180111, 0x11190111, 0x111a0111, 0x111b0111, 0x111c0111, 0x111d0111, 0xffffffff, 0xffffffff, + 0x10d60111, 0x0000a211, 0x0000a311, 0x0000a411, 0x0000a511, 0xffffffff, 0xffffffff, 0xffffffff, + 0x10e90111, 0x10ea0111, 0x10eb0111, 0x10f00111, 0x10f50111, 0x10f60111, 0x10fe0111, 0x11020111, + 0x10de0111, 0x10e00111, 0x11130111, 0x11140111, 0x02600111, 0x02610111, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0x02cd0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x0000a711, 0x0000a811, 0x0000a911, 0xffffffff, 0x111e0111, 0x111f0111, 0x11200111, + 0x11210111, 0x11220111, 0x11230111, 0x11240111, 0x11260111, 0xffffffff, 0xffffffff, 0x11280111, + 0x11290111, 0xffffffff, 0xffffffff, 0x112a0111, 0x112b0111, 0x112c0111, 0x112d0111, 0x112e0111, + 0x112f0111, 0x11300111, 0x11310111, 0x11320111, 0x11330111, 0x11340111, 0x11350111, 0x11360111, + 0x11370111, 0x11380111, 0x11390111, 0x113a0111, 0x113b0111, 0x113c0111, 0x113d0111, 0x113e0111, + 0x113f0111, 0xffffffff, 0x11400111, 0x11410111, 0x11420111, 0x11430111, 0x11440111, 0x11450111, + 0x11460111, 0xffffffff, 0x11480111, 0xffffffff, 0xffffffff, 0xffffffff, 0x114a0111, 0x114b0111, + 0x114c0111, 0x114d0111, 0xffffffff, 0xffffffff, 0x0000a611, 0xffffffff, 0x114e0111, 0x114f0111, + 0x11500111, 0x11510111, 0x11520111, 0x11530111, 0x11540111, 0xffffffff, 0xffffffff, 0x11570111, + 0x11580111, 0xffffffff, 0xffffffff, 0x11590111, 0x115a0111, 0x115b0111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x115c0111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x11380111, 0x11390111, 0xffffffff, 0x11450111, + 0x11250111, 0x11270111, 0x11550111, 0x11560111, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0x11470111, 0x11490111, 0x09e30111, 0x09e40111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, + 0x09c10111, 0x09c20111, 0x030d0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0a00 .. 0x0aff */ + 0xffffffff, 0xffffffff, 0x0000ab11, 0xffffffff, 0xffffffff, 0x11620111, 0x11630111, 0x11670111, + 0x11680111, 0x115f0111, 0x11600111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x11690111, + 0x11640111, 0xffffffff, 0xffffffff, 0x11610111, 0x11650111, 0x116c0111, 0x116d0111, 0x116e0111, + 0x116f0111, 0x11700111, 0x11710111, 0x11720111, 0x11730111, 0x11740111, 0x11750111, 0x11760111, + 0x11770111, 0x11780111, 0x11790111, 0x117a0111, 0x117b0111, 0x117c0111, 0x117d0111, 0x117e0111, + 0x117f0111, 0xffffffff, 0x11800111, 0x11810111, 0x11820111, 0x11830111, 0x11840111, 0x11850111, + 0x11860111, 0xffffffff, 0x11870111, 0x11870111, 0xffffffff, 0x11880111, 0x116a0111, 0xffffffff, + 0x116a0111, 0x116b0111, 0xffffffff, 0xffffffff, 0x0000aa11, 0xffffffff, 0x118a0111, 0x118b0111, + 0x118c0111, 0x118d0111, 0x118e0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x118f0111, + 0x11900111, 0xffffffff, 0xffffffff, 0x11910111, 0x11920111, 0x11930111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x116d0111, 0x116e0111, 0x11730111, 0x11890111, 0xffffffff, 0x11810111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0x0000ac11, 0x0000ad11, 0x11660111, 0x115e0111, 0x115d0111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x0000af11, 0x0000b011, 0x0000b111, 0xffffffff, 0x11950111, 0x11960111, 0x11970111, + 0x11980111, 0x11990111, 0x119a0111, 0x119b0111, 0xffffffff, 0x119d0111, 0xffffffff, 0x119e0111, + 0x119f0111, 0x11a00111, 0xffffffff, 0x11a10111, 0x11a20111, 0x11a30111, 0x11a40111, 0x11a50111, + 0x11a60111, 0x11a70111, 0x11a80111, 0x11a90111, 0x11aa0111, 0x11ab0111, 0x11ac0111, 0x11ad0111, + 0x11ae0111, 0x11af0111, 0x11b00111, 0x11b10111, 0x11b20111, 0x11b30111, 0x11b40111, 0x11b50111, + 0x11b60111, 0xffffffff, 0x11b70111, 0x11b80111, 0x11b90111, 0x11ba0111, 0x11bb0111, 0x11bc0111, + 0x11bd0111, 0xffffffff, 0x11be0111, 0x11bf0111, 0xffffffff, 0x11c00111, 0x11c10111, 0x11c20111, + 0x11c30111, 0x11c40111, 0xffffffff, 0xffffffff, 0x0000ae11, 0x11c50111, 0x11c60111, 0x11c70111, + 0x11c80111, 0x11c90111, 0x11ca0111, 0x11cb0111, 0x11cc0111, 0x11cd0111, 0xffffffff, 0x11ce0111, + 0x11cf0111, 0x11d00111, 0xffffffff, 0x11d10111, 0x11d20111, 0x11d30111, 0xffffffff, 0xffffffff, + 0x11940111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x119c0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0b00 .. 0x0bff */ + 0xffffffff, 0x0000b311, 0x0000b411, 0x0000b511, 0xffffffff, 0x11d40111, 0x11d50111, 0x11d60111, + 0x11d70111, 0x11d80111, 0x11d90111, 0x11da0111, 0x11dc0111, 0xffffffff, 0xffffffff, 0x11de0111, + 0x11df0111, 0xffffffff, 0xffffffff, 0x11e00111, 0x11e10111, 0x11e20111, 0x11e30111, 0x11e40111, + 0x11e50111, 0x11e60111, 0x11e70111, 0x11e80111, 0x11e90111, 0x11ea0111, 0x11eb0111, 0x11ec0111, + 0x11ed0111, 0x11ee0111, 0x11ef0111, 0x11f00111, 0x11f10111, 0x11f20111, 0x11f30111, 0x11f40111, + 0x11f50111, 0xffffffff, 0x11f60111, 0x11f70111, 0x11f80111, 0x11f90111, 0x11fa0111, 0x11fb0111, + 0x11fd0111, 0xffffffff, 0x11fe0111, 0x11ff0111, 0xffffffff, 0xffffffff, 0x12000111, 0x12010111, + 0x12020111, 0x12030111, 0xffffffff, 0xffffffff, 0x0000b211, 0x12040111, 0x12050111, 0x12060111, + 0x12070111, 0x12080111, 0x12090111, 0x120a0111, 0xffffffff, 0xffffffff, 0xffffffff, 0x120b0111, + 0x120c0111, 0xffffffff, 0xffffffff, 0x120d0111, 0x120e0111, 0x120f0111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12100111, 0x12110111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x11ee0111, 0x11ef0111, 0xffffffff, 0x11fc0111, + 0x11db0111, 0x11dd0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0x030e0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x0000b611, 0x12120111, 0xffffffff, 0x12130111, 0x12140111, 0x12150111, + 0x12160111, 0x12170111, 0x12180111, 0xffffffff, 0xffffffff, 0xffffffff, 0x12190111, 0x121a0111, + 0x121b0111, 0xffffffff, 0x121c0111, 0x121d0111, 0x121e0111, 0x121f0111, 0xffffffff, 0xffffffff, + 0xffffffff, 0x12200111, 0x12210111, 0xffffffff, 0x12220111, 0xffffffff, 0x12230111, 0x12240111, + 0xffffffff, 0xffffffff, 0xffffffff, 0x12250111, 0x12260111, 0xffffffff, 0xffffffff, 0xffffffff, + 0x12270111, 0x12280111, 0x12290111, 0xffffffff, 0xffffffff, 0xffffffff, 0x122a0111, 0x122b0111, + 0x122c0111, 0x122d0111, 0x122e0111, 0x122f0111, 0x12300111, 0x12310111, 0xffffffff, 0x12320111, + 0x12330111, 0x12340111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12350111, 0x12360111, + 0x12370111, 0x12380111, 0x12390111, 0xffffffff, 0xffffffff, 0xffffffff, 0x123a0111, 0x123b0111, + 0x123c0111, 0xffffffff, 0x123d0111, 0x123e0111, 0x123f0111, 0x12400111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12410111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0x09c30111, 0x09c40111, 0x09c50111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0c00 .. 0x0cff */ + 0xffffffff, 0x0000b711, 0x0000b811, 0x0000b911, 0xffffffff, 0x12420111, 0x12430111, 0x12440111, + 0x12450111, 0x12460111, 0x12470111, 0x12480111, 0x124a0111, 0xffffffff, 0x124c0111, 0x124d0111, + 0x124e0111, 0xffffffff, 0x124f0111, 0x12500111, 0x12510111, 0x12520111, 0x12530111, 0x12540111, + 0x12550111, 0x12560111, 0x12570111, 0x12580111, 0x12590111, 0x125a0111, 0x125b0111, 0x125c0111, + 0x125d0111, 0x125e0111, 0x125f0111, 0x12600111, 0x12610111, 0x12620111, 0x12630111, 0x12640111, + 0x12650111, 0xffffffff, 0x12660111, 0x12670111, 0x12680111, 0x12690111, 0x126a0111, 0x126b0111, + 0x126c0111, 0x126d0111, 0x126e0111, 0x126f0111, 0xffffffff, 0x12700111, 0x12710111, 0x12720111, + 0x12730111, 0x12740111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12750111, 0x12760111, + 0x12770111, 0x12780111, 0x12790111, 0x127a0111, 0x127b0111, 0xffffffff, 0x127c0111, 0x127d0111, + 0x127e0111, 0xffffffff, 0x127f0111, 0x12800111, 0x12810111, 0x12820111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12830111, 0x12840111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x12490111, 0x124b0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x0000ba11, 0x0000bb11, 0xffffffff, 0x12850111, 0x12860111, 0x12870111, + 0x12880111, 0x12890111, 0x128a0111, 0x128b0111, 0x128d0111, 0xffffffff, 0x128f0111, 0x12900111, + 0x12910111, 0xffffffff, 0x12920111, 0x12930111, 0x12940111, 0x12950111, 0x12960111, 0x12970111, + 0x12980111, 0x12990111, 0x129a0111, 0x129b0111, 0x129c0111, 0x129d0111, 0x129e0111, 0x129f0111, + 0x12a00111, 0x12a10111, 0x12a20111, 0x12a30111, 0x12a40111, 0x12a50111, 0x12a60111, 0x12a70111, + 0x12a80111, 0xffffffff, 0x12a90111, 0x12aa0111, 0x12ab0111, 0x12ac0111, 0x12ad0111, 0x12ae0111, + 0x12af0111, 0x12b00111, 0x12b10111, 0x12b70111, 0xffffffff, 0x12b20111, 0x12b30111, 0x12b40111, + 0x12b50111, 0x12b60111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12b90111, 0x12ba0111, + 0x12bb0111, 0x12bc0111, 0x12bd0111, 0x12be0111, 0x12bf0111, 0xffffffff, 0x12c00111, 0x12c10111, + 0x12c20111, 0xffffffff, 0x12c30111, 0x12c40111, 0x12c50111, 0x12c60111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12c70111, 0x12c80111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12b80111, 0xffffffff, + 0x128c0111, 0x128e0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0d00 .. 0x0dff */ + 0xffffffff, 0xffffffff, 0x0000bc11, 0x0000bd11, 0xffffffff, 0x12c90111, 0x12ca0111, 0x12cb0111, + 0x12cc0111, 0x12cd0111, 0x12ce0111, 0x12cf0111, 0x12d10111, 0xffffffff, 0x12d30111, 0x12d40111, + 0x12d50111, 0xffffffff, 0x12d60111, 0x12d70111, 0x12d80111, 0x12d90111, 0x12da0111, 0x12db0111, + 0x12dc0111, 0x12dd0111, 0x12de0111, 0x12df0111, 0x12e00111, 0x12e10111, 0x12e20111, 0x12e30111, + 0x12e40111, 0x12e50111, 0x12e60111, 0x12e70111, 0x12e80111, 0x12e90111, 0x12ea0111, 0x12eb0111, + 0x12ec0111, 0xffffffff, 0x12ed0111, 0x12ee0111, 0x12ef0111, 0x12f00111, 0x12f10111, 0x12f20111, + 0x12f30111, 0x12f40111, 0x12f50111, 0x12f60111, 0x12f70111, 0x12f80111, 0x12f90111, 0x12fa0111, + 0x12fb0111, 0x12fc0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x12fd0111, 0x12fe0111, + 0x12ff0111, 0x13000111, 0x13010111, 0x13020111, 0xffffffff, 0xffffffff, 0x13030111, 0x13040111, + 0x13050111, 0xffffffff, 0x13060111, 0x13070111, 0x13080111, 0x13090111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x130a0111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x12d00111, 0x12d20111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0b0111, 0x0a0c0111, + 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, 0x0a130111, 0x0a140111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x0000be11, 0x0000bf11, 0xffffffff, 0x130b0111, 0x130c0111, 0x130d0111, + 0x130e0111, 0x130f0111, 0x13100111, 0x13110111, 0x13120111, 0x13130111, 0x13140111, 0x13150111, + 0x13160111, 0x13170111, 0x13180111, 0x13190111, 0x131a0111, 0x131b0111, 0x131c0111, 0xffffffff, + 0xffffffff, 0xffffffff, 0x131d0111, 0x131e0111, 0x131f0111, 0x13200111, 0x13210111, 0x13220111, + 0x13230111, 0x13240111, 0x13250111, 0x13260111, 0x13270111, 0x13280111, 0x13290111, 0x132a0111, + 0x132b0111, 0x132c0111, 0x132d0111, 0x132e0111, 0x132f0111, 0x13300111, 0x13310111, 0x13320111, + 0x13330111, 0x13340111, 0xffffffff, 0x13350111, 0x13360111, 0x13370111, 0x13380111, 0x13390111, + 0x133a0111, 0x133b0111, 0x133c0111, 0x133d0111, 0xffffffff, 0x133e0111, 0xffffffff, 0xffffffff, + 0x133f0111, 0x13400111, 0x13410111, 0x13420111, 0x13430111, 0x13440111, 0x13450111, 0xffffffff, + 0xffffffff, 0xffffffff, 0x13460111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x13470111, + 0x13480111, 0x13490111, 0x134a0111, 0x134b0111, 0x134c0111, 0xffffffff, 0x134d0111, 0xffffffff, + 0x134e0111, 0x134f0111, 0x13500111, 0x13510111, 0x13520111, 0x13530111, 0x13540111, 0x13550111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x13560111, 0x13570111, 0x02ce0111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0e00 .. 0x0eff */ + 0xffffffff, 0x13580111, 0x13590111, 0x135a0111, 0x135b0111, 0x135c0111, 0x135d0111, 0x135e0111, + 0x135f0111, 0x13600111, 0x13610111, 0x13620111, 0x13630111, 0x13640111, 0x13650111, 0x13660111, + 0x13670111, 0x13680111, 0x13690111, 0x136a0111, 0x136b0111, 0x136c0111, 0x136d0111, 0x136e0111, + 0x136f0111, 0x13700111, 0x13710111, 0x13720111, 0x13730111, 0x13740111, 0x13750111, 0x13760111, + 0x13770111, 0x13780111, 0x13790111, 0x137a0111, 0x137b0111, 0x137c0111, 0x137d0111, 0x137e0111, + 0x137f0111, 0x13800111, 0x13810111, 0x13820111, 0x13830111, 0x13840111, 0x13850111, 0x13860111, + 0x13870111, 0x13880111, 0x13890111, 0x138a0111, 0x138b0111, 0x138c0111, 0x138d0111, 0x138e0111, + 0x138f0111, 0x13900111, 0x13910111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x09e50111, + 0x13920111, 0x13930111, 0x13940111, 0x13950111, 0x13960111, 0x13970111, 0x09d50111, 0x0000c011, + 0x0000c111, 0x0000c211, 0x0000c311, 0x0000c411, 0x13980111, 0x13990111, 0x00000001, 0x030f0111, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x02cf0111, 0x02d00111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x139a0111, 0x139b0111, 0xffffffff, 0x139c0111, 0xffffffff, 0xffffffff, 0x139d0111, + 0x139e0111, 0xffffffff, 0x139f0111, 0xffffffff, 0xffffffff, 0x13a00111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x13a10111, 0x13a20111, 0x13a30111, 0x13a40111, + 0xffffffff, 0x13a50111, 0x13a60111, 0x13a70111, 0x13a80111, 0x13a90111, 0x13aa0111, 0x13ab0111, + 0xffffffff, 0x13ac0111, 0x13ad0111, 0x13ae0111, 0xffffffff, 0x13af0111, 0xffffffff, 0x13b00111, + 0xffffffff, 0xffffffff, 0x13b10111, 0x13b20111, 0xffffffff, 0x13b30111, 0x13b40111, 0x13b50111, + 0x13b60111, 0x13b70111, 0x13b80111, 0x13b90111, 0x13ba0111, 0x13bb0111, 0x13bc0111, 0x13bd0111, + 0x13be0111, 0x13bf0111, 0xffffffff, 0x13c00111, 0x13c10111, 0x13c20111, 0xffffffff, 0xffffffff, + 0x13c30111, 0x13c40111, 0x13c50111, 0x13c60111, 0x13c70111, 0xffffffff, 0x09d60111, 0xffffffff, + 0x0000c511, 0x0000c611, 0x0000c711, 0x0000c811, 0x13c80111, 0x13c90111, 0xffffffff, 0xffffffff, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0xffffffff, 0xffffffff, 0x13b20121, 0x13b20121, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x0f00 .. 0x0fff */ + 0x140e0121, 0x03100111, 0x03110111, 0x03120111, 0x02d10111, 0x02d20111, 0x02d30111, 0x02d40111, + 0x02d50111, 0x02d60111, 0x02d70111, 0x02d80111, 0x02d80121, 0x02d90111, 0x02da0111, 0x02db0111, + 0x02dc0111, 0x02dd0111, 0x02de0111, 0x03130111, 0x02460111, 0x03140111, 0x03150111, 0x03160111, + 0x00000001, 0x00000001, 0x03170111, 0x03180111, 0x03190111, 0x031a0111, 0x031b0111, 0x031c0111, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, + 0x0a120111, 0x0a130111, 0x0a140111, 0x0a0b0111, 0x031d0111, 0x00000001, 0x031e0111, 0x00000001, + 0x031f0111, 0x0000c911, 0x02800111, 0x02810111, 0x02820111, 0x02830111, 0x03200111, 0x03210111, + 0x13ca0111, 0x13cc0111, 0x13ce0111, 0x13ce0111, 0x13d00111, 0x13d20111, 0x13d40111, 0x13d60111, + 0xffffffff, 0x13d80111, 0x13da0111, 0x13dc0111, 0x13de0111, 0x13de0111, 0x13e00111, 0x13e20111, + 0x13e40111, 0x13e60111, 0x13e60111, 0x13e80111, 0x13ea0111, 0x13ec0111, 0x13ee0111, 0x13ee0111, + 0x13f00111, 0x13f20111, 0x13f40111, 0x13f60111, 0x13f60111, 0x13f80111, 0x13fa0111, 0x13fc0111, + 0x13fe0111, 0x14000111, 0x14020111, 0x14040111, 0x14060111, 0x14080111, 0x140a0111, 0x140c0111, + 0x140e0111, 0x13ca0111, 0x14020121, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x14140111, 0x14150111, 0x14160111, 0x14190111, 0x141a0111, 0x141b0111, 0x141c0111, + 0x141d0111, 0x141e0111, 0x141f0111, 0x14200111, 0x14210111, 0x14220111, 0x0000ca11, 0x0000cb11, + 0x14170111, 0x14180111, 0x00000001, 0x00000001, 0x14230111, 0x02df0111, 0x00000001, 0x00000001, + 0x14100111, 0x14110111, 0x14120111, 0x14130111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x13cb0111, 0x13cd0111, 0x13cf0111, 0x13cf0111, 0x13d10111, 0x13d30111, 0x13d50111, 0x13d70111, + 0xffffffff, 0x13d90111, 0x13db0111, 0x13dd0111, 0x13df0111, 0x13df0111, 0x13e10111, 0x13e30111, + 0x13e50111, 0x13e70111, 0x13e70111, 0x13e90111, 0x13eb0111, 0x13ed0111, 0x13ef0111, 0x13ef0111, + 0x13f10111, 0x13f30111, 0x13f50111, 0x13f70111, 0x13f70111, 0x13f90111, 0x13fb0111, 0x13fd0111, + 0x13ff0111, 0x14010111, 0x14030111, 0x14050111, 0x14070111, 0x14090111, 0x140b0111, 0x140d0111, + 0x140f0111, 0x13cb0111, 0x13f90121, 0x14010121, 0x14030121, 0xffffffff, 0x03220111, 0x03230111, + 0x03240111, 0x03250111, 0x03260111, 0x03270111, 0x03280111, 0x03290111, 0x00000001, 0x032a0111, + 0x032b0111, 0x032c0111, 0x032d0111, 0x032e0111, 0x032f0111, 0xffffffff, 0xffffffff, 0x03300111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1000 .. 0x10ff */ + 0x14240111, 0x14250111, 0x14260111, 0x14270111, 0x14280111, 0x14290111, 0x142a0111, 0x142b0111, + 0x142c0111, 0x142d0111, 0x142e0111, 0x142f0111, 0x14300111, 0x14310111, 0x14320111, 0x14330111, + 0x14340111, 0x14350111, 0x14360111, 0x14370111, 0x14380111, 0x14390111, 0x143a0111, 0x143b0111, + 0x143c0111, 0x143d0111, 0x143e0111, 0x143f0111, 0x14400111, 0x14410111, 0x14440111, 0x14450111, + 0x14460111, 0x14470111, 0xffffffff, 0x14480111, 0x14490111, 0x144a0111, 0x144b0111, 0x144c0111, + 0xffffffff, 0x144d0111, 0x144e0111, 0xffffffff, 0x14530111, 0x14540111, 0x14550111, 0x14560111, + 0x14570111, 0x14580111, 0x14590111, 0xffffffff, 0xffffffff, 0xffffffff, 0x0000cc11, 0x0000cd11, + 0x0000ce11, 0x145e0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x02620111, 0x02630111, 0x02e00111, 0x02e10111, 0x02e20111, 0x02e30111, + 0x14420111, 0x14430111, 0x144f0111, 0x14500111, 0x14510111, 0x14520111, 0x145a0111, 0x145b0111, + 0x145c0111, 0x145d0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0e690121, 0x0e6a0121, 0x0e6b0121, 0x0e6c0121, 0x0e6d0121, 0x0e6e0121, 0x0e6f0121, 0x0e710121, + 0x0e720121, 0x0e730121, 0x0e740121, 0x0e750121, 0x0e760121, 0x0e780121, 0x0e790121, 0x0e7a0121, + 0x0e7b0121, 0x0e7c0121, 0x0e7d0121, 0x0e7f0121, 0x0e800121, 0x0e810121, 0x0e820121, 0x0e830121, + 0x0e840121, 0x0e850121, 0x0e860121, 0x0e870121, 0x0e880121, 0x0e890121, 0x0e8a0121, 0x0e8c0121, + 0x0e8d0121, 0x0e700121, 0x0e770121, 0x0e7e0121, 0x0e8b0121, 0x0e8e0121, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0e690111, 0x0e6a0111, 0x0e6b0111, 0x0e6c0111, 0x0e6d0111, 0x0e6e0111, 0x0e6f0111, 0x0e710111, + 0x0e720111, 0x0e730111, 0x0e740111, 0x0e750111, 0x0e760111, 0x0e780111, 0x0e790111, 0x0e7a0111, + 0x0e7b0111, 0x0e7c0111, 0x0e7d0111, 0x0e7f0111, 0x0e800111, 0x0e810111, 0x0e820111, 0x0e830111, + 0x0e840111, 0x0e850111, 0x0e860111, 0x0e870111, 0x0e880111, 0x0e890111, 0x0e8a0111, 0x0e8c0111, + 0x0e8d0111, 0x0e700111, 0x0e770111, 0x0e7e0111, 0x0e8b0111, 0x0e8e0111, 0x0e8f0111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x02670111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1100 .. 0x11ff */ + 0x18310111, 0x18320111, 0x18330111, 0x18340111, 0x18350111, 0x18360111, 0x18370111, 0x18380111, + 0x18390111, 0x183a0111, 0x183b0111, 0x183c0111, 0x183d0111, 0x183e0111, 0x183f0111, 0x18400111, + 0x18410111, 0x18420111, 0x18430111, 0x18440111, 0x18450111, 0x18460111, 0x18470111, 0x18480111, + 0x18490111, 0x184a0111, 0x184b0111, 0x184c0111, 0x184d0111, 0x184e0111, 0x184f0111, 0x18500111, + 0x18510111, 0x18520111, 0x18530111, 0x18540111, 0x18550111, 0x18560111, 0x18570111, 0x18580111, + 0x18590111, 0x185a0111, 0x185b0111, 0x185c0111, 0x185d0111, 0x185e0111, 0x185f0111, 0x18600111, + 0x18610111, 0x18620111, 0x18630111, 0x18640111, 0x18650111, 0x18660111, 0x18670111, 0x18680111, + 0x18690111, 0x186a0111, 0x186b0111, 0x186c0111, 0x186d0111, 0x186e0111, 0x186f0111, 0x18700111, + 0x18710111, 0x18720111, 0x18730111, 0x18740111, 0x18750111, 0x18760111, 0x18770111, 0x18780111, + 0x18790111, 0x187a0111, 0x187b0111, 0x187c0111, 0x187d0111, 0x187e0111, 0x187f0111, 0x18800111, + 0x18810111, 0x18820111, 0x18830111, 0x18840111, 0x18850111, 0x18860111, 0x18870111, 0x18880111, + 0x18890111, 0x188a0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x188b0111, + 0x188c0111, 0x188d0111, 0x188e0111, 0x188f0111, 0x18900111, 0x18910111, 0x18920111, 0x18930111, + 0x18940111, 0x18950111, 0x18960111, 0x18970111, 0x18980111, 0x18990111, 0x189a0111, 0x189b0111, + 0x189c0111, 0x189d0111, 0x189e0111, 0x189f0111, 0x18a00111, 0x18a10111, 0x18a20111, 0x18a30111, + 0x18a40111, 0x18a50111, 0x18a60111, 0x18a70111, 0x18a80111, 0x18a90111, 0x18aa0111, 0x18ab0111, + 0x18ac0111, 0x18ad0111, 0x18ae0111, 0x18af0111, 0x18b00111, 0x18b10111, 0x18b20111, 0x18b30111, + 0x18b40111, 0x18b50111, 0x18b60111, 0x18b70111, 0x18b80111, 0x18b90111, 0x18ba0111, 0x18bb0111, + 0x18bc0111, 0x18bd0111, 0x18be0111, 0x18bf0111, 0x18c00111, 0x18c10111, 0x18c20111, 0x18c30111, + 0x18c40111, 0x18c50111, 0x18c60111, 0x18c70111, 0x18c80111, 0x18c90111, 0x18ca0111, 0x18cb0111, + 0x18cc0111, 0x18cd0111, 0x18ce0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x18cf0111, 0x18d00111, 0x18d10111, 0x18d20111, 0x18d30111, 0x18d40111, 0x18d50111, 0x18d60111, + 0x18d70111, 0x18d80111, 0x18d90111, 0x18da0111, 0x18db0111, 0x18dc0111, 0x18dd0111, 0x18de0111, + 0x18df0111, 0x18e00111, 0x18e10111, 0x18e20111, 0x18e30111, 0x18e40111, 0x18e50111, 0x18e60111, + 0x18e70111, 0x18e80111, 0x18e90111, 0x18ea0111, 0x18eb0111, 0x18ec0111, 0x18ed0111, 0x18ee0111, + 0x18ef0111, 0x18f00111, 0x18f10111, 0x18f20111, 0x18f30111, 0x18f40111, 0x18f50111, 0x18f60111, + 0x18f70111, 0x18f80111, 0x18f90111, 0x18fa0111, 0x18fb0111, 0x18fc0111, 0x18fd0111, 0x18fe0111, + 0x18ff0111, 0x19000111, 0x19010111, 0x19020111, 0x19030111, 0x19040111, 0x19050111, 0x19060111, + 0x19070111, 0x19080111, 0x19090111, 0x190a0111, 0x190b0111, 0x190c0111, 0x190d0111, 0x190e0111, + 0x190f0111, 0x19100111, 0x19110111, 0x19120111, 0x19130111, 0x19140111, 0x19150111, 0x19160111, + 0x19170111, 0x19180111, 0x19190111, 0x191a0111, 0x191b0111, 0x191c0111, 0x191d0111, 0x191e0111, + 0x191f0111, 0x19200111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1200 .. 0x12ff */ + 0x0f990111, 0x0f9a0111, 0x0f9b0111, 0x0f9c0111, 0x0f9d0111, 0x0f9e0111, 0x0f9f0111, 0xffffffff, + 0x0fa00111, 0x0fa10111, 0x0fa20111, 0x0fa30111, 0x0fa40111, 0x0fa50111, 0x0fa60111, 0x0fa70111, + 0x0fa80111, 0x0fa90111, 0x0faa0111, 0x0fab0111, 0x0fac0111, 0x0fad0111, 0x0fae0111, 0x0faf0111, + 0x0fb00111, 0x0fb10111, 0x0fb20111, 0x0fb30111, 0x0fb40111, 0x0fb50111, 0x0fb60111, 0x0fb70111, + 0x0fb80111, 0x0fb90111, 0x0fba0111, 0x0fbb0111, 0x0fbc0111, 0x0fbd0111, 0x0fbe0111, 0x0fbf0111, + 0x0fc00111, 0x0fc10111, 0x0fc20111, 0x0fc30111, 0x0fc40111, 0x0fc50111, 0x0fc60111, 0x0fc70111, + 0x0fc80111, 0x0fc90111, 0x0fca0111, 0x0fcb0111, 0x0fcc0111, 0x0fcd0111, 0x0fce0111, 0x0fcf0111, + 0x0fd00111, 0x0fd10111, 0x0fd20111, 0x0fd30111, 0x0fd40111, 0x0fd50111, 0x0fd60111, 0x0fd70111, + 0x0fd80111, 0x0fd90111, 0x0fda0111, 0x0fdb0111, 0x0fdc0111, 0x0fdd0111, 0x0fde0111, 0xffffffff, + 0x0fdf0111, 0xffffffff, 0x0fe00111, 0x0fe10111, 0x0fe20111, 0x0fe30111, 0xffffffff, 0xffffffff, + 0x0fe40111, 0x0fe50111, 0x0fe60111, 0x0fe70111, 0x0fe80111, 0x0fe90111, 0x0fea0111, 0xffffffff, + 0x0feb0111, 0xffffffff, 0x0fec0111, 0x0fed0111, 0x0fee0111, 0x0fef0111, 0xffffffff, 0xffffffff, + 0x0ff00111, 0x0ff10111, 0x0ff20111, 0x0ff30111, 0x0ff40111, 0x0ff50111, 0x0ff60111, 0x0ff70111, + 0x0ff80111, 0x0ff90111, 0x0ffa0111, 0x0ffb0111, 0x0ffc0111, 0x0ffd0111, 0x0ffe0111, 0x0fff0111, + 0x10000111, 0x10010111, 0x10020111, 0x10030111, 0x10040111, 0x10050111, 0x10060111, 0x10070111, + 0x10080111, 0x10090111, 0x100a0111, 0x100b0111, 0x100c0111, 0x100d0111, 0x100e0111, 0x100f0111, + 0x10100111, 0x10110111, 0x10120111, 0x10130111, 0x10140111, 0x10150111, 0x10160111, 0xffffffff, + 0x10170111, 0xffffffff, 0x10180111, 0x10190111, 0x101a0111, 0x101b0111, 0xffffffff, 0xffffffff, + 0x101c0111, 0x101d0111, 0x101e0111, 0x101f0111, 0x10200111, 0x10210111, 0x10220111, 0x10230111, + 0x10240111, 0x10250111, 0x10260111, 0x10270111, 0x10280111, 0x10290111, 0x102a0111, 0x102b0111, + 0x102c0111, 0x102d0111, 0x102e0111, 0x102f0111, 0x10300111, 0x10310111, 0x10320111, 0x10330111, + 0x10340111, 0x10350111, 0x10360111, 0x10370111, 0x10380111, 0x10390111, 0x103a0111, 0xffffffff, + 0x103b0111, 0xffffffff, 0x103c0111, 0x103d0111, 0x103e0111, 0x103f0111, 0xffffffff, 0xffffffff, + 0x10400111, 0x10410111, 0x10420111, 0x10430111, 0x10440111, 0x10450111, 0x10460111, 0xffffffff, + 0x10470111, 0xffffffff, 0x10480111, 0x10490111, 0x104a0111, 0x104b0111, 0xffffffff, 0xffffffff, + 0x104c0111, 0x104d0111, 0x104e0111, 0x104f0111, 0x10500111, 0x10510111, 0x10520111, 0xffffffff, + 0x10530111, 0x10540111, 0x10550111, 0x10560111, 0x10570111, 0x10580111, 0x10590111, 0xffffffff, + 0x105a0111, 0x105b0111, 0x105c0111, 0x105d0111, 0x105e0111, 0x105f0111, 0x10600111, 0x10610111, + 0x10620111, 0x10630111, 0x10640111, 0x10650111, 0x10660111, 0x10670111, 0x10680111, 0x10690111, + 0x106a0111, 0x106b0111, 0x106c0111, 0x106d0111, 0x106e0111, 0x106f0111, 0x10700111, 0xffffffff, + 0x10710111, 0x10720111, 0x10730111, 0x10740111, 0x10750111, 0x10760111, 0x10770111, 0x10780111, + 0x10790111, 0x107a0111, 0x107b0111, 0x107c0111, 0x107d0111, 0x107e0111, 0x107f0111, 0x10800111, + /* 0x1300 .. 0x13ff */ + 0x10810111, 0x10820111, 0x10830111, 0x10840111, 0x10850111, 0x10860111, 0x10870111, 0x10880111, + 0x10890111, 0x108a0111, 0x108b0111, 0x108c0111, 0x108d0111, 0x108e0111, 0x108f0111, 0xffffffff, + 0x10900111, 0xffffffff, 0x10910111, 0x10920111, 0x10930111, 0x10940111, 0xffffffff, 0xffffffff, + 0x10950111, 0x10960111, 0x10970111, 0x10980111, 0x10990111, 0x109a0111, 0x109b0111, 0xffffffff, + 0x109c0111, 0x109d0111, 0x109e0111, 0x109f0111, 0x10a00111, 0x10a10111, 0x10a20111, 0x10a30111, + 0x10a40111, 0x10a50111, 0x10a60111, 0x10a70111, 0x10a80111, 0x10a90111, 0x10aa0111, 0x10ab0111, + 0x10ac0111, 0x10ad0111, 0x10ae0111, 0x10af0111, 0x10b00111, 0x10b10111, 0x10b20111, 0x10b30111, + 0x10b40111, 0x10b50111, 0x10b60111, 0x10b70111, 0x10b80111, 0x10b90111, 0x10ba0111, 0x10bb0111, + 0x10bc0111, 0x10bd0111, 0x10be0111, 0x10bf0111, 0x10c00111, 0x10c10111, 0x10c20111, 0xffffffff, + 0x10c30111, 0x10c40111, 0x10c50111, 0x10c60111, 0x10c70111, 0x10c80111, 0x10c90111, 0x10ca0111, + 0x10cb0111, 0x10cc0111, 0x10cd0111, 0x10ce0111, 0x10cf0111, 0x10d00111, 0x10d10111, 0x10d20111, + 0x10d30111, 0x10d40111, 0x10d50111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x023f0111, 0x025a0111, 0x02400111, 0x02410111, 0x02420111, 0x02430111, 0x02530111, + 0x02680111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x09c60111, 0x09c70111, 0x09c80111, 0x09c90111, 0x09ca0111, 0x09cb0111, + 0x09cc0111, 0x09cd0111, 0x09ce0111, 0x09cf0111, 0x09d00111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x15280111, 0x15290111, 0x152a0111, 0x152b0111, 0x152c0111, 0x152d0111, 0x152e0111, 0x152f0111, + 0x15300111, 0x15310111, 0x15320111, 0x15330111, 0x15340111, 0x15350111, 0x15360111, 0x15370111, + 0x15380111, 0x15390111, 0x153a0111, 0x153b0111, 0x153c0111, 0x153d0111, 0x153e0111, 0x153f0111, + 0x15400111, 0x15410111, 0x15420111, 0x15430111, 0x15440111, 0x15450111, 0x15460111, 0x15470111, + 0x15480111, 0x15490111, 0x154a0111, 0x154b0111, 0x154c0111, 0x154d0111, 0x154e0111, 0x154f0111, + 0x15500111, 0x15510111, 0x15520111, 0x15530111, 0x15540111, 0x15550111, 0x15560111, 0x15570111, + 0x15580111, 0x15590111, 0x155a0111, 0x155b0111, 0x155c0111, 0x155d0111, 0x155e0111, 0x155f0111, + 0x15600111, 0x15610111, 0x15620111, 0x15630111, 0x15640111, 0x15650111, 0x15660111, 0x15670111, + 0x15680111, 0x15690111, 0x156a0111, 0x156b0111, 0x156c0111, 0x156d0111, 0x156e0111, 0x156f0111, + 0x15700111, 0x15710111, 0x15720111, 0x15730111, 0x15740111, 0x15750111, 0x15760111, 0x15770111, + 0x15780111, 0x15790111, 0x157a0111, 0x157b0111, 0x157c0111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1400 .. 0x14ff */ + 0xffffffff, 0x157d0111, 0x157e0111, 0x157f0111, 0x15800111, 0x15810111, 0x15820111, 0x15830111, + 0x15840111, 0x15850111, 0x15860111, 0x15870111, 0x15880111, 0x15890111, 0x158a0111, 0x158b0111, + 0x158c0111, 0x158d0111, 0x158e0111, 0x158f0111, 0x15900111, 0x15910111, 0x15920111, 0x15930111, + 0x15940111, 0x15950111, 0x15960111, 0x15970111, 0x15980111, 0x15990111, 0x159a0111, 0x159b0111, + 0x159c0111, 0x159d0111, 0x159e0111, 0x159f0111, 0x15a00111, 0x15a10111, 0x15a20111, 0x15a30111, + 0x15a40111, 0x15a50111, 0x15a60111, 0x15a70111, 0x15a80111, 0x15a90111, 0x15aa0111, 0x15ab0111, + 0x15ac0111, 0x15ad0111, 0x15ae0111, 0x15af0111, 0x15b00111, 0x15b10111, 0x15b20111, 0x15b30111, + 0x15b40111, 0x15b50111, 0x15b60111, 0x15b70111, 0x15b80111, 0x15b90111, 0x15ba0111, 0x15bb0111, + 0x15bc0111, 0x15bd0111, 0x15be0111, 0x15bf0111, 0x15c00111, 0x15c10111, 0x15c20111, 0x15c30111, + 0x15c40111, 0x15c50111, 0x15c60111, 0x15c70111, 0x15c80111, 0x15c90111, 0x15ca0111, 0x15cb0111, + 0x15cc0111, 0x15cd0111, 0x15ce0111, 0x15cf0111, 0x15d00111, 0x15d10111, 0x15d20111, 0x15d30111, + 0x15d40111, 0x15d50111, 0x15d60111, 0x15d70111, 0x15d80111, 0x15d90111, 0x15da0111, 0x15db0111, + 0x15dc0111, 0x15dd0111, 0x15de0111, 0x15df0111, 0x15e00111, 0x15e10111, 0x15e20111, 0x15e30111, + 0x15e40111, 0x15e50111, 0x15e60111, 0x15e70111, 0x15e80111, 0x15e90111, 0x15ea0111, 0x15eb0111, + 0x15ec0111, 0x15ed0111, 0x15ee0111, 0x15ef0111, 0x15f00111, 0x15f10111, 0x15f20111, 0x15f30111, + 0x15f40111, 0x15f50111, 0x15f60111, 0x15f70111, 0x15f80111, 0x15f90111, 0x15fa0111, 0x15fb0111, + 0x15fc0111, 0x15fd0111, 0x15fe0111, 0x15ff0111, 0x16000111, 0x16010111, 0x16020111, 0x16030111, + 0x16040111, 0x16050111, 0x16060111, 0x16070111, 0x16080111, 0x16090111, 0x160a0111, 0x160b0111, + 0x160c0111, 0x160d0111, 0x160e0111, 0x160f0111, 0x16100111, 0x16110111, 0x16120111, 0x16130111, + 0x16140111, 0x16150111, 0x16160111, 0x16170111, 0x16180111, 0x16190111, 0x161a0111, 0x161b0111, + 0x161c0111, 0x161d0111, 0x161e0111, 0x161f0111, 0x16200111, 0x16210111, 0x16220111, 0x16230111, + 0x16240111, 0x16250111, 0x16260111, 0x16270111, 0x16280111, 0x16290111, 0x162a0111, 0x162b0111, + 0x162c0111, 0x162d0111, 0x162e0111, 0x162f0111, 0x16300111, 0x16310111, 0x16320111, 0x16330111, + 0x16340111, 0x16350111, 0x16360111, 0x16370111, 0x16380111, 0x16390111, 0x163a0111, 0x163b0111, + 0x163c0111, 0x163d0111, 0x163e0111, 0x163f0111, 0x16400111, 0x16410111, 0x16420111, 0x16430111, + 0x16440111, 0x16450111, 0x16460111, 0x16470111, 0x16480111, 0x16490111, 0x164a0111, 0x164b0111, + 0x164c0111, 0x164d0111, 0x164e0111, 0x164f0111, 0x16500111, 0x16510111, 0x16520111, 0x16530111, + 0x16540111, 0x16550111, 0x16560111, 0x16570111, 0x16580111, 0x16590111, 0x165a0111, 0x165b0111, + 0x165c0111, 0x165d0111, 0x165e0111, 0x165f0111, 0x16600111, 0x16610111, 0x16620111, 0x16630111, + 0x16640111, 0x16650111, 0x16660111, 0x16670111, 0x16680111, 0x16690111, 0x166a0111, 0x166b0111, + 0x166c0111, 0x166d0111, 0x166e0111, 0x166f0111, 0x16700111, 0x16710111, 0x16720111, 0x16730111, + 0x16740111, 0x16750111, 0x16760111, 0x16770111, 0x16780111, 0x16790111, 0x167a0111, 0x167b0111, + /* 0x1500 .. 0x15ff */ + 0x167c0111, 0x167d0111, 0x167e0111, 0x167f0111, 0x16800111, 0x16810111, 0x16820111, 0x16830111, + 0x16840111, 0x16850111, 0x16860111, 0x16870111, 0x16880111, 0x16890111, 0x168a0111, 0x168b0111, + 0x168c0111, 0x168d0111, 0x168e0111, 0x168f0111, 0x16900111, 0x16910111, 0x16920111, 0x16930111, + 0x16940111, 0x16950111, 0x16960111, 0x16970111, 0x16980111, 0x16990111, 0x169a0111, 0x169b0111, + 0x169c0111, 0x169d0111, 0x169e0111, 0x169f0111, 0x16a00111, 0x16a10111, 0x16a20111, 0x16a30111, + 0x16a40111, 0x16a50111, 0x16a60111, 0x16a70111, 0x16a80111, 0x16a90111, 0x16aa0111, 0x16ab0111, + 0x16ac0111, 0x16ad0111, 0x16ae0111, 0x16af0111, 0x16b00111, 0x16b10111, 0x16b20111, 0x16b30111, + 0x16b40111, 0x16b50111, 0x16b60111, 0x16b70111, 0x16b80111, 0x16b90111, 0x16ba0111, 0x16bb0111, + 0x16bc0111, 0x16bd0111, 0x16be0111, 0x16bf0111, 0x16c00111, 0x16c10111, 0x16c20111, 0x16c30111, + 0x16c40111, 0x16c50111, 0x16c60111, 0x16c70111, 0x16c80111, 0x16c90111, 0x16ca0111, 0x16cb0111, + 0x16cc0111, 0x16cd0111, 0x16ce0111, 0x16cf0111, 0x16d00111, 0x16d10111, 0x16d20111, 0x16d30111, + 0x16d40111, 0x16d50111, 0x16d60111, 0x16d70111, 0x16d80111, 0x16d90111, 0x16da0111, 0x16db0111, + 0x16dc0111, 0x16dd0111, 0x16de0111, 0x16df0111, 0x16e00111, 0x16e10111, 0x16e20111, 0x16e30111, + 0x16e40111, 0x16e50111, 0x16e60111, 0x16e70111, 0x16e80111, 0x16e90111, 0x16ea0111, 0x16eb0111, + 0x16ec0111, 0x16ed0111, 0x16ee0111, 0x16ef0111, 0x16f00111, 0x16f10111, 0x16f20111, 0x16f30111, + 0x16f40111, 0x16f50111, 0x16f60111, 0x16f70111, 0x172a0111, 0x16f80111, 0x16fa0111, 0x16fb0111, + 0x16fc0111, 0x16fd0111, 0x16fe0111, 0x16ff0111, 0x17000111, 0x17010111, 0x17020111, 0x17030111, + 0x17040111, 0x17050111, 0x17060111, 0x17070111, 0x17080111, 0x17090111, 0x170b0111, 0x170c0111, + 0x170d0111, 0x170e0111, 0x170f0111, 0x17100111, 0x17110111, 0x17120111, 0x17190111, 0x171a0111, + 0x171b0111, 0x171c0111, 0x171d0111, 0x171e0111, 0x171f0111, 0x17200111, 0x17210111, 0x17220111, + 0x17230111, 0x17240111, 0x17250111, 0x17260111, 0x17270111, 0x17280111, 0x17290111, 0x172b0111, + 0x172c0111, 0x172d0111, 0x172e0111, 0x172f0111, 0x17300111, 0x17310111, 0x17320111, 0x17330111, + 0x17340111, 0x17350111, 0x17360111, 0x17370111, 0x17380111, 0x17390111, 0x173a0111, 0x173b0111, + 0x173c0111, 0x173d0111, 0x173e0111, 0x173f0111, 0x17400111, 0x17410111, 0x17420111, 0x17430111, + 0x17440111, 0x17450111, 0x17460111, 0x17470111, 0x17480111, 0x17490111, 0x174a0111, 0x174b0111, + 0x174c0111, 0x174d0111, 0x174e0111, 0x174f0111, 0x17500111, 0x17510111, 0x17520111, 0x17530111, + 0x17540111, 0x17550111, 0x17560111, 0x17570111, 0x17580111, 0x17590111, 0x175a0111, 0x175b0111, + 0x175c0111, 0x175d0111, 0x175e0111, 0x175f0111, 0x17600111, 0x17610111, 0x17620111, 0x17630111, + 0x17640111, 0x17650111, 0x17660111, 0x17670111, 0x17680111, 0x17690111, 0x176a0111, 0x176b0111, + 0x176c0111, 0x176d0111, 0x176e0111, 0x176f0111, 0x17700111, 0x17710111, 0x17720111, 0x17730111, + 0x17740111, 0x17750111, 0x17760111, 0x17770111, 0x17780111, 0x17790111, 0x177a0111, 0x177b0111, + 0x177c0111, 0x177d0111, 0x177e0111, 0x177f0111, 0x17800111, 0x17810111, 0x17820111, 0x17830111, + /* 0x1600 .. 0x16ff */ + 0x17840111, 0x17850111, 0x17860111, 0x17870111, 0x17880111, 0x17890111, 0x178a0111, 0x178b0111, + 0x178c0111, 0x178d0111, 0x178e0111, 0x178f0111, 0x17900111, 0x17910111, 0x17920111, 0x17930111, + 0x17940111, 0x17950111, 0x17960111, 0x17970111, 0x17980111, 0x17990111, 0x179a0111, 0x179b0111, + 0x179c0111, 0x179d0111, 0x179e0111, 0x179f0111, 0x17a00111, 0x17a10111, 0x17a20111, 0x17a30111, + 0x17a40111, 0x17a50111, 0x17a60111, 0x17a70111, 0x17a80111, 0x17a90111, 0x17aa0111, 0x17ab0111, + 0x17ac0111, 0x17ad0111, 0x17ae0111, 0x17af0111, 0x17b00111, 0x17b10111, 0x17b20111, 0x17b30111, + 0x17b40111, 0x17b50111, 0x17b60111, 0x17b70111, 0x17b80111, 0x17b90111, 0x17ba0111, 0x17bb0111, + 0x17bc0111, 0x17bd0111, 0x17be0111, 0x17bf0111, 0x17c00111, 0x17c10111, 0x17c20111, 0x17c30111, + 0x17c40111, 0x17c50111, 0x17c60111, 0x17c70111, 0x17c80111, 0x17c90111, 0x17ca0111, 0x17cb0111, + 0x17cc0111, 0x17cd0111, 0x17ce0111, 0x17cf0111, 0x17d00111, 0x17d10111, 0x17d20111, 0x17d30111, + 0x17d40111, 0x17d50111, 0x17d60111, 0x17d70111, 0x17d80111, 0x17d90111, 0x17da0111, 0x17db0111, + 0x17dc0111, 0x17dd0111, 0x17de0111, 0x17df0111, 0x17e00111, 0x17e10111, 0x17e20111, 0x17e30111, + 0x17e40111, 0x17e50111, 0x17e60111, 0x17e70111, 0x17e80111, 0x17e90111, 0x17ea0111, 0x17eb0111, + 0x17ec0111, 0x17ed0111, 0x17ee0111, 0x17ef0111, 0x17f00111, 0x03310111, 0x025d0111, 0x16f90111, + 0x170a0111, 0x17130111, 0x17140111, 0x17150111, 0x17160111, 0x17170111, 0x17180111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x020a0111, 0x17f10111, 0x17f20111, 0x17f30111, 0x17f40111, 0x17f50111, 0x17f60111, 0x17f70111, + 0x17f80111, 0x17f90111, 0x17fa0111, 0x17fb0111, 0x17fc0111, 0x17fd0111, 0x17fe0111, 0x17ff0111, + 0x18000111, 0x18010111, 0x18020111, 0x18030111, 0x18040111, 0x18050111, 0x18060111, 0x18070111, + 0x18080111, 0x18090111, 0x180a0111, 0x02840111, 0x02850111, 0xffffffff, 0xffffffff, 0xffffffff, + 0x180b0111, 0x180b0121, 0x180c0111, 0x18280111, 0x180c0121, 0x180c0121, 0x180d0111, 0x180d0121, + 0x180e0111, 0x180e0121, 0x18260111, 0x18270111, 0x180e0121, 0x180e0121, 0x180e0121, 0x180f0111, + 0x18100111, 0x18110111, 0x18120111, 0x18120121, 0x18120121, 0x18120121, 0x18120121, 0x18130111, + 0x182b0111, 0x18140111, 0x18150111, 0x18150121, 0x18150121, 0x18150121, 0x18160111, 0x18160121, + 0x18160121, 0x18170111, 0x18170121, 0x18180111, 0x18180121, 0x18190111, 0x18190121, 0x181a0111, + 0x181b0111, 0x181c0111, 0x181d0111, 0x181d0121, 0x181d0121, 0x181d0121, 0x181d0121, 0x181e0111, + 0x181e0121, 0x181e0121, 0x181f0111, 0x181f0121, 0x181f0121, 0x181b0121, 0x18200111, 0x18210111, + 0x18210121, 0x18210121, 0x18220111, 0x18220121, 0x18230111, 0x18230121, 0x18240111, 0x18250111, + 0x18290111, 0x182d0111, 0x182e0111, 0x182a0111, 0x182c0111, 0x182f0111, 0x18300111, 0x18300121, + 0x18300121, 0x18140121, 0x181d0121, 0x02480111, 0x02490111, 0x024a0111, 0x18190121, 0x18210121, + 0x180d0121, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1700 .. 0x17ff */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x145f0111, 0x14600111, 0x14610111, 0x14620111, 0x14630111, 0x14640111, 0x14650111, 0x14660111, + 0x14670111, 0x14680111, 0x14690111, 0x146a0111, 0x146b0111, 0x146c0111, 0x146d0111, 0x146e0111, + 0x146f0111, 0x14700111, 0x14710111, 0x14720111, 0x14730111, 0x14740111, 0x14750111, 0x14760111, + 0x14770111, 0x14780111, 0x14790111, 0x147a0111, 0x147b0111, 0x147c0111, 0x147d0111, 0x147e0111, + 0x147f0111, 0x14800111, 0x14810111, 0x14820111, 0x14830111, 0x14840111, 0x14850111, 0x14860111, + 0x14870111, 0x14880111, 0x14890111, 0x148a0111, 0x148b0111, 0x148c0111, 0x148d0111, 0x148e0111, + 0x148f0111, 0x14900111, 0x14910111, 0x14920111, 0x14930111, 0x14940111, 0x14950111, 0x14960111, + 0x14970111, 0x14980111, 0x14990111, 0x149a0111, 0x149b0111, 0x149c0111, 0x149d0111, 0x149e0111, + 0x149f0111, 0x14a00111, 0x14a10111, 0x14a20111, 0x14a30111, 0x14a40111, 0x0000cf11, 0x0000d011, + 0x0000d111, 0x0000d211, 0x0000d311, 0x0000d411, 0x0000d511, 0x0000d611, 0x0000d711, 0x0000d811, + 0x0000d911, 0x0000da11, 0x14a50111, 0x0000db11, 0x02640111, 0x02650111, 0x02470111, 0x02e40111, + 0x02e50111, 0x02e60111, 0x02e70111, 0x09e60111, 0x02e80111, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1800 .. 0x18ff */ + 0x02cb0111, 0x02560111, 0x02320111, 0x025b0111, 0x02440111, 0x02450111, 0x02230111, 0x02240111, + 0x02330111, 0x025c0111, 0x02cc0111, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0x0a0b0111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x14ae0111, 0x14b00111, 0x14b30111, 0x14b90111, 0x14bb0111, 0x14be0111, 0x14c00111, 0x14c30111, + 0x14c40111, 0x14c50111, 0x14ca0111, 0x14cc0111, 0x14cf0111, 0x14d10111, 0x14d60111, 0x14d80111, + 0x14d90111, 0x14da0111, 0x14e10111, 0x14e40111, 0x14e70111, 0x14ec0111, 0x14f00111, 0x14f30111, + 0x14f50111, 0x14f70111, 0x14fa0111, 0x14ff0111, 0x15000111, 0x15030111, 0x15070111, 0x150a0111, + 0x150b0111, 0x150c0111, 0x150d0111, 0x14ad0111, 0x14b10111, 0x14b40111, 0x14ba0111, 0x14bc0111, + 0x14bf0111, 0x14c10111, 0x14c60111, 0x14cb0111, 0x14cd0111, 0x14d00111, 0x14d20111, 0x14d70111, + 0x14e20111, 0x14e50111, 0x14e80111, 0x14ed0111, 0x15010111, 0x14f10111, 0x14f60111, 0x14fb0111, + 0x15050111, 0x15080111, 0x150e0111, 0x150f0111, 0x14ea0111, 0x14b20111, 0x14b50111, 0x14b80111, + 0x14c20111, 0x14bd0111, 0x14c70111, 0x14fc0111, 0x14d30111, 0x14d50111, 0x14ce0111, 0x14db0111, + 0x14e30111, 0x14e60111, 0x14ee0111, 0x14f80111, 0x15060111, 0x15090111, 0x15020111, 0x15040111, + 0x15100111, 0x14e90111, 0x14f20111, 0x14b60111, 0x14fd0111, 0x14f40111, 0x14f90111, 0x14ef0111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x14a60111, 0x14a70111, 0x14a80111, 0x14a90111, 0x14aa0111, 0x14ab0111, 0x14ac0111, 0x14af0111, + 0x14b70111, 0x14fe0111, 0x14c80111, 0x14eb0111, 0x15110111, 0x15130111, 0x15140111, 0x15160111, + 0x15170111, 0x151a0111, 0x151c0111, 0x151d0111, 0x151f0111, 0x15210111, 0x15230111, 0x15240111, + 0x15180111, 0x15220111, 0x14d40111, 0x14c90111, 0x14dc0111, 0x14dd0111, 0x15120111, 0x15150111, + 0x15190111, 0x151b0111, 0x14de0111, 0x15200111, 0x14df0111, 0x14e00111, 0x15250111, 0x15260111, + 0x151e0111, 0x15270111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1e00 .. 0x1eff */ + 0x0a150151, 0x0a150111, 0x0a290141, 0x0a290111, 0x0a290141, 0x0a290111, 0x0a290141, 0x0a290111, + 0x0a3d0151, 0x0a3d0111, 0x0a490151, 0x0a490111, 0x0a490151, 0x0a490111, 0x0a490151, 0x0a490111, + 0x0a490151, 0x0a490111, 0x0a490151, 0x0a490111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, + 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a910151, 0x0a910111, + 0x0a990151, 0x0a990111, 0x0ab90151, 0x0ab90111, 0x0ab90151, 0x0ab90111, 0x0ab90151, 0x0ab90111, + 0x0ab90151, 0x0ab90111, 0x0ab90151, 0x0ab90111, 0x0ad30161, 0x0ad30111, 0x0ad30161, 0x0ad30111, + 0x0af70141, 0x0af70111, 0x0af70141, 0x0af70111, 0x0af70141, 0x0af70111, 0x0b030161, 0x0b030111, + 0x0b030161, 0x0b030111, 0x0b030161, 0x0b030111, 0x0b030161, 0x0b030111, 0x0b2b0151, 0x0b2b0111, + 0x0b2b0151, 0x0b2b0111, 0x0b2b0151, 0x0b2b0111, 0x0b330151, 0x0b330111, 0x0b330151, 0x0b330111, + 0x0b330151, 0x0b330111, 0x0b330151, 0x0b330111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0b670141, 0x0b670111, 0x0b670141, 0x0b670111, + 0x0b7f0141, 0x0b7f0111, 0x0b7f0141, 0x0b7f0111, 0x0b7f0141, 0x0b7f0111, 0x0b7f0141, 0x0b7f0111, + 0x0ba70151, 0x0ba70111, 0x0ba70151, 0x0ba70111, 0x0ba70151, 0x0ba70111, 0x0ba70151, 0x0ba70111, + 0x0ba70151, 0x0ba70111, 0x0bbf0151, 0x0bbf0111, 0x0bbf0151, 0x0bbf0111, 0x0bbf0151, 0x0bbf0111, + 0x0bbf0151, 0x0bbf0111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, + 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bef0151, 0x0bef0111, 0x0bef0151, 0x0bef0111, + 0x0bfb0141, 0x0bfb0111, 0x0bfb0141, 0x0bfb0111, 0x0bfb0141, 0x0bfb0111, 0x0bfb0141, 0x0bfb0111, + 0x0bfb0141, 0x0bfb0111, 0x0c030151, 0x0c030111, 0x0c030151, 0x0c030111, 0x0c070141, 0x0c070111, + 0x0c130141, 0x0c130111, 0x0c130141, 0x0c130111, 0x0c130141, 0x0c130111, 0x0ab90111, 0x0bbf0111, + 0x0bfb0111, 0x0c070111, 0x0a150131, 0x0ba70131, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, + 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, + 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, 0x0a150151, 0x0a150111, + 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, + 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, 0x0a650151, 0x0a650111, + 0x0ad30161, 0x0ad30111, 0x0ad30161, 0x0ad30111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, + 0x0b4b0161, 0x0b4b0111, 0x0b4b0161, 0x0b4b0111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, + 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, 0x0bd70141, 0x0bd70111, + 0x0bd70141, 0x0bd70111, 0x0c070141, 0x0c070111, 0x0c070141, 0x0c070111, 0x0c070141, 0x0c070111, + 0x0c070141, 0x0c070111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x1f00 .. 0x1fff */ + 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, + 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, + 0x0c950111, 0x0c950111, 0x0c950111, 0x0c950111, 0x0c950111, 0x0c950111, 0xffffffff, 0xffffffff, + 0x0c950131, 0x0c950131, 0x0c950131, 0x0c950131, 0x0c950131, 0x0c950131, 0xffffffff, 0xffffffff, + 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, + 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, + 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, + 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, + 0x0ca20111, 0x0ca20111, 0x0ca20111, 0x0ca20111, 0x0ca20111, 0x0ca20111, 0xffffffff, 0xffffffff, + 0x0ca20121, 0x0ca20121, 0x0ca20121, 0x0ca20121, 0x0ca20121, 0x0ca20121, 0xffffffff, 0xffffffff, + 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca80111, + 0xffffffff, 0x0ca80121, 0xffffffff, 0x0ca80121, 0xffffffff, 0x0ca80121, 0xffffffff, 0x0ca80121, + 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, + 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, + 0x0c910111, 0x0c910111, 0x0c950111, 0x0c950111, 0x0c990111, 0x0c990111, 0x0c9b0111, 0x0c9b0111, + 0x0ca20111, 0x0ca20111, 0x0ca80111, 0x0ca80111, 0x0cac0111, 0x0cac0111, 0xffffffff, 0xffffffff, + 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, + 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, + 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, 0x0c990111, + 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, 0x0c990121, + 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0x0cac0111, + 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x0cac0121, + 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0x0c910111, 0xffffffff, 0x0c910111, 0x0c910111, + 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x0c910121, 0x02170111, 0x0c9b0111, 0x02170111, + 0x021d0111, 0x02140111, 0x0c990111, 0x0c990111, 0x0c990111, 0xffffffff, 0x0c990111, 0x0c990111, + 0x0c950131, 0x0c950131, 0x0c990121, 0x0c990121, 0x0c990121, 0x02170111, 0x02170111, 0x02170111, + 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0x0c9b0111, 0xffffffff, 0xffffffff, 0x0c9b0111, 0x0c9b0111, + 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0x0c9b0121, 0xffffffff, 0x02180111, 0x02180111, 0x02180111, + 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca80111, 0x0ca50111, 0x0ca50111, 0x0ca80111, 0x0ca80111, + 0x0ca80121, 0x0ca80121, 0x0ca80121, 0x0ca80121, 0x0ca50131, 0x02140111, 0x02140111, 0x020c0111, + 0xffffffff, 0xffffffff, 0x0cac0111, 0x0cac0111, 0x0cac0111, 0xffffffff, 0x0cac0111, 0x0cac0111, + 0x0ca20121, 0x0ca20121, 0x0cac0121, 0x0cac0121, 0x0cac0121, 0x020d0111, 0x02180111, 0xffffffff, + /* 0x2000 .. 0x20ff */ + 0x02090131, 0x02090131, 0x02090131, 0x02090131, 0x02090131, 0x02090131, 0x02090131, 0x02090141, + 0x02090131, 0x02090131, 0x02090131, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02250111, 0x02250121, 0x02260111, 0x02270111, 0x02280111, 0x02290111, 0x03a90111, 0x021c0111, + 0x026a0111, 0x026b0111, 0x026c0111, 0x026d0111, 0x02710111, 0x02720111, 0x02730111, 0x02740111, + 0x02ae0111, 0x02af0111, 0x02b00111, 0x02b10111, 0x02550131, 0x02550131, 0x02550131, 0x02b20111, + 0x02070111, 0x02080111, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x02090141, + 0x02ac0111, 0x02ad0111, 0x02b60111, 0x02b60121, 0x02b60121, 0x02b70111, 0x02b70121, 0x02b70121, + 0x02b90111, 0x026e0111, 0x026f0111, 0x02ba0111, 0x024b0131, 0x02540111, 0x02110111, 0x02bb0111, + 0x02bc0111, 0x02bd0111, 0x02be0111, 0x02b30111, 0x02a50111, 0x02860111, 0x02870111, 0xffffffff, + 0x024e0131, 0x024b0131, 0x02a80111, 0x029e0111, 0x02b40111, 0x02b50111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0a0b0151, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0f0151, 0x0a100151, 0x0a110151, 0x0a120151, + 0x0a130151, 0x0a140151, 0x039f0151, 0x03ab0121, 0x03a40141, 0x027a0151, 0x027b0141, 0x0b3301a1, + 0x0a0b0161, 0x0a0c0161, 0x0a0d0161, 0x0a0e0161, 0x0a0f0161, 0x0a100161, 0x0a110161, 0x0a120161, + 0x0a130161, 0x0a140161, 0x039f0161, 0x03ab0131, 0x03a40151, 0x027a0161, 0x027b0151, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x09e70111, 0x09e80111, 0x09e90111, 0x09ea0111, 0x09eb0111, 0x09ec0111, 0x09ed0111, 0x09ee0111, + 0x0b7f0161, 0x09ef0111, 0x09f00111, 0x09f10111, 0x09f20111, 0x09f30111, 0x09f40111, 0x09f50111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0000e411, 0x0000e511, 0x0000e611, 0x0000e711, 0x0000e811, 0x0000e911, 0x0000ea11, 0x0000eb11, + 0x0000ec11, 0x0000ed11, 0x0000ee11, 0x0000ef11, 0x0000f011, 0x0000f111, 0x0000f211, 0x0000f311, + 0x0000f411, 0x0000f511, 0x0000f611, 0x0000f711, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2100 .. 0x21ff */ + 0x0a150131, 0x0a150131, 0x0a3d0181, 0x030a0121, 0x09f60111, 0x0a3d0131, 0x0a3d0131, 0x0a710131, + 0x09f70111, 0x030a0121, 0x0a990131, 0x0ab90171, 0x0ab90171, 0x0ab90171, 0x0ab90131, 0x0ac50121, + 0x0ad30191, 0x0ad30191, 0x0b030191, 0x0b030141, 0x09f80111, 0x0b330181, 0x0b330171, 0x09f90111, + 0x09fa0111, 0x0b670161, 0x0b730161, 0x0b7f0171, 0x0b7f0171, 0x0b7f0171, 0x09fb0111, 0x09fc0111, + 0x0ba70181, 0x0bbf0171, 0x0bbf0191, 0x09fd0111, 0x0c130161, 0x09fe0111, 0x0cac0121, 0x09ff0111, + 0x0c130161, 0x0a000111, 0x0af70141, 0x0a150151, 0x0a290161, 0x0a3d0181, 0x0a010111, 0x0a650131, + 0x0a650171, 0x0a910171, 0x0a020111, 0x0b2b0181, 0x0b4b0141, 0x0eb70121, 0x0eb80121, 0x0eb90121, + 0x0eba0121, 0x0ad30141, 0x0a030111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0c0171, 0x0a0d0171, 0x0a0c0171, 0x0a0d0171, 0x0a0e0171, + 0x0a0f0171, 0x0a0c0171, 0x0a100171, 0x0a0c0171, 0x0a0e0171, 0x0a100171, 0x0a120171, 0x0a0c0171, + 0x0ad30181, 0x0ad30181, 0x0ad30181, 0x0ad30181, 0x0bef0171, 0x0bef0171, 0x0bef0171, 0x0bef0171, + 0x0ad30181, 0x0c030171, 0x0c030171, 0x0c030171, 0x0b030181, 0x0a3d0171, 0x0a490171, 0x0b2b0171, + 0x0ad30131, 0x0ad30131, 0x0ad30131, 0x0ad30131, 0x0bef0131, 0x0bef0131, 0x0bef0131, 0x0bef0131, + 0x0ad30131, 0x0c030131, 0x0c030131, 0x0c030131, 0x0b030131, 0x0a3d0131, 0x0a490131, 0x0b2b0131, + 0x0a040111, 0x0a050111, 0x0a060111, 0x0a070111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x03320111, 0x03340111, 0x03330111, 0x03350111, 0x03360111, 0x03370111, 0x03380111, 0x03390111, + 0x033a0111, 0x033b0111, 0x03320111, 0x03330111, 0x033c0111, 0x033d0111, 0x033e0111, 0x033f0111, + 0x03400111, 0x03410111, 0x03420111, 0x03430111, 0x03440111, 0x03450111, 0x03460111, 0x03470111, + 0x03480111, 0x03490111, 0x034a0111, 0x034b0111, 0x034c0111, 0x034d0111, 0x03360111, 0x034e0111, + 0x034f0111, 0x03500111, 0x03510111, 0x03520111, 0x03530111, 0x03540111, 0x03550111, 0x03560111, + 0x03570111, 0x03580111, 0x03590111, 0x035a0111, 0x035b0111, 0x035c0111, 0x035d0111, 0x035e0111, + 0x035f0111, 0x03600111, 0x03610111, 0x03620111, 0x03630111, 0x03640111, 0x03650111, 0x03660111, + 0x03670111, 0x03680111, 0x03690111, 0x036a0111, 0x036b0111, 0x036c0111, 0x03700111, 0x036e0111, + 0x036c0111, 0x036d0111, 0x036e0111, 0x036f0111, 0x03700111, 0x03710111, 0x03720111, 0x03730111, + 0x03740111, 0x03750111, 0x03760111, 0x03770111, 0x03780111, 0x03790111, 0x037a0111, 0x037b0111, + 0x037c0111, 0x037d0111, 0x037e0111, 0x037f0111, 0x03800111, 0x03810111, 0x03820111, 0x03830111, + 0x03840111, 0x03850111, 0x03860111, 0x03870111, 0x03880111, 0x03890111, 0x038a0111, 0x038b0111, + 0x038c0111, 0x038d0111, 0x038e0111, 0x038f0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2200 .. 0x22ff */ + 0x03900111, 0x03910111, 0x03920111, 0x03930111, 0x03930111, 0x03940111, 0x03950111, 0x03960111, + 0x03970111, 0x03970111, 0x03980111, 0x03990111, 0x03990111, 0x039a0111, 0x039b0111, 0x039c0111, + 0x039d0111, 0x039e0111, 0x03ab0111, 0x03ac0111, 0x03ad0111, 0x03ae0111, 0x03af0111, 0x03b00111, + 0x03b10111, 0x03b20111, 0x03b30111, 0x03b40111, 0x03b50111, 0x03b60111, 0x03b70111, 0x03b80111, + 0x03b90111, 0x03ba0111, 0x03bb0111, 0x03bc0111, 0x03bc0111, 0x03bd0111, 0x03bd0111, 0x03be0111, + 0x03bf0111, 0x03c00111, 0x03c10111, 0x03c20111, 0x03c20121, 0x03c20121, 0x03c30111, 0x03c30121, + 0x03c30121, 0x03c40111, 0x03c50111, 0x03c60111, 0x03c70111, 0x03c80111, 0x03c90111, 0x03ca0111, + 0x03cb0111, 0x03cc0111, 0x03cd0111, 0x03ce0111, 0x03cf0111, 0x03d00111, 0x03d10111, 0x03d20111, + 0x03d30111, 0x03cf0111, 0x03d40111, 0x03d50111, 0x03d50111, 0x03d60111, 0x03d70111, 0x03d60111, + 0x03d80111, 0x03d80111, 0x03d90111, 0x03da0111, 0x03db0111, 0x03dc0111, 0x03dd0111, 0x03de0111, + 0x03df0111, 0x03e00111, 0x03e10111, 0x03e20111, 0x03e30111, 0x03e40111, 0x03e50111, 0x03e60111, + 0x03e70111, 0x03e80111, 0x03e90111, 0x03ea0111, 0x03eb0111, 0x03ec0111, 0x03ed0111, 0x03ee0111, + 0x03a40111, 0x03ef0111, 0x03ef0111, 0x03f00111, 0x03f10111, 0x03f20111, 0x03f30111, 0x03f40111, + 0x03f50111, 0x03f60111, 0x03f70111, 0x03f80111, 0x03f90111, 0x03dc0111, 0x03a30111, 0x03a50111, + 0x03f10111, 0x03f20111, 0x03fa0111, 0x03fb0111, 0x03fa0111, 0x03fb0111, 0x03fc0111, 0x03fd0111, + 0x03fc0111, 0x03fd0111, 0x03fe0111, 0x03ff0111, 0x04000111, 0x04010111, 0x04020111, 0x04030111, + 0x03fe0111, 0x03ff0111, 0x04040111, 0x04050111, 0x04040111, 0x04050111, 0x04060111, 0x04070111, + 0x04060111, 0x04070111, 0x04080111, 0x04090111, 0x040a0111, 0x040b0111, 0x040c0111, 0x040d0111, + 0x040e0111, 0x040f0111, 0x04100111, 0x04110111, 0x04120111, 0x04130111, 0x04140111, 0x04150111, + 0x04160111, 0x04170111, 0x04180111, 0x04190111, 0x041a0111, 0x041b0111, 0x041c0111, 0x041d0111, + 0x041e0111, 0x041f0111, 0x04200111, 0x04210111, 0x04220111, 0x04230111, 0x04240111, 0x04250111, + 0x04260111, 0x04270111, 0x04280111, 0x04290111, 0x04200111, 0x04260111, 0x04270111, 0x04290111, + 0x042a0111, 0x042b0111, 0x042c0111, 0x042d0111, 0x042e0111, 0x042f0111, 0x04300111, 0x04310111, + 0x04320111, 0x04330111, 0x04340111, 0x04350111, 0x04360111, 0x04370111, 0x04380111, 0x04390111, + 0x043a0111, 0x043b0111, 0x043c0111, 0x043d0111, 0x043e0111, 0x043f0111, 0x04400111, 0x04410111, + 0x04420111, 0x04430111, 0x04440111, 0x04450111, 0x04460111, 0x04470111, 0x04480111, 0x04490111, + 0x044a0111, 0x044b0111, 0x044c0111, 0x044d0111, 0x044e0111, 0x044f0111, 0x04500111, 0x04510111, + 0x04520111, 0x04530111, 0x04540111, 0x04550111, 0x04560111, 0x04570111, 0x04580111, 0x04590111, + 0x04000111, 0x04010111, 0x040f0111, 0x04100111, 0x045a0111, 0x045b0111, 0x045c0111, 0x045d0111, + 0x045e0111, 0x045f0111, 0x042c0111, 0x042d0111, 0x042e0111, 0x042f0111, 0x04600111, 0x04610111, + 0x04620111, 0x04630111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2300 .. 0x23ff */ + 0x04640111, 0x04650111, 0x04660111, 0x04670111, 0x04680111, 0x04690111, 0x046a0111, 0x046b0111, + 0x046c0111, 0x046d0111, 0x046e0111, 0x046f0111, 0x04700111, 0x04710111, 0x04720111, 0x04730111, + 0x04740111, 0x04750111, 0x04760111, 0x04770111, 0x04780111, 0x04790111, 0x047a0111, 0x047b0111, + 0x047c0111, 0x047d0111, 0x047e0111, 0x047f0111, 0x04800111, 0x04810111, 0x04820111, 0x04830111, + 0x04840111, 0x04850111, 0x04860111, 0x04870111, 0x04880111, 0x04890111, 0x048a0111, 0x048b0111, + 0x048c0111, 0x02880111, 0x02890111, 0x048d0111, 0x048e0111, 0x048f0111, 0x04900111, 0x04910111, + 0x04920111, 0x04930111, 0x04940111, 0x04950111, 0x04960111, 0x04970111, 0x04980111, 0x04990111, + 0x049a0111, 0x049b0111, 0x049c0111, 0x049d0111, 0x049e0111, 0x049f0111, 0x04a00111, 0x04a10111, + 0x04a20111, 0x04a30111, 0x04a40111, 0x04a50111, 0x04a60111, 0x04a70111, 0x04a80111, 0x04a90111, + 0x04aa0111, 0x04ab0111, 0x04ac0111, 0x04ad0111, 0x04ae0111, 0x04af0111, 0x04b00111, 0x04b10111, + 0x04b20111, 0x04b30111, 0x04b40111, 0x04b50111, 0x04b60111, 0x04b70111, 0x04b80111, 0x04b90111, + 0x04ba0111, 0x04bb0111, 0x04bc0111, 0x04bd0111, 0x04be0111, 0x04bf0111, 0x04c00111, 0x04c10111, + 0x04c20111, 0x04c30111, 0x04c40111, 0x04c50111, 0x04c60111, 0x04c70111, 0x04c80111, 0x04c90111, + 0x04ca0111, 0x04cb0111, 0x04cc0111, 0x04cd0111, 0x04ce0111, 0x04cf0111, 0x04d00111, 0x04d10111, + 0x04d20111, 0x04d30111, 0x04d40111, 0x04d50111, 0x04d60111, 0x04d70111, 0x04d80111, 0x04d90111, + 0x04da0111, 0x04db0111, 0x04dc0111, 0x04dd0111, 0xffffffff, 0x04de0111, 0x04df0111, 0x04e00111, + 0x04e10111, 0x04e20111, 0x04e30111, 0x04e40111, 0x04e50111, 0x04e60111, 0x04e70111, 0x04e80111, + 0x04e90111, 0x04ea0111, 0x04eb0111, 0x04ec0111, 0x04ed0111, 0x04ee0111, 0x04ef0111, 0x04f00111, + 0x04f10111, 0x04f20111, 0x04f30111, 0x04f40111, 0x04f50111, 0x04f60111, 0x04f70111, 0x04f80111, + 0x04f90111, 0x04fa0111, 0x04fb0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2400 .. 0x24ff */ + 0x04fc0111, 0x04fd0111, 0x04fe0111, 0x04ff0111, 0x05000111, 0x05010111, 0x05020111, 0x05030111, + 0x05040111, 0x05050111, 0x05060111, 0x05070111, 0x05080111, 0x05090111, 0x050a0111, 0x050b0111, + 0x050c0111, 0x050d0111, 0x050e0111, 0x050f0111, 0x05100111, 0x05110111, 0x05120111, 0x05130111, + 0x05140111, 0x05150111, 0x05160111, 0x05170111, 0x05180111, 0x05190111, 0x051a0111, 0x051b0111, + 0x051c0111, 0x051d0111, 0x051e0111, 0x051f0111, 0x05200111, 0x05210111, 0x05220111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x05230111, 0x05240111, 0x05250111, 0x05260111, 0x05270111, 0x05280111, 0x05290111, 0x052a0111, + 0x052b0111, 0x052c0111, 0x052d0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a0c0141, 0x0a0d0141, 0x0a0e0141, 0x0a0f0141, 0x0a100141, 0x0a110141, 0x0a120141, 0x0a130141, + 0x0a140141, 0x0a0c0141, 0x0a0c0141, 0x0a0c0141, 0x0a0c0141, 0x0a0c0141, 0x0a0c0141, 0x0a0c0141, + 0x0a0c0141, 0x0a0c0141, 0x0a0c0141, 0x0a0d0141, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x0a0c0131, 0x0a0d0131, 0x0a0e0131, 0x0a0f0131, 0x0a100131, 0x0a110131, 0x0a120131, 0x0a130131, + 0x0a140131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, + 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0d0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x0a150171, 0x0a290171, + 0x0a3d0191, 0x0a490181, 0x0a650181, 0x0a910181, 0x0a990171, 0x0ab90181, 0x0ad301a1, 0x0ae70161, + 0x0af70161, 0x0b0301a1, 0x0b2b0191, 0x0b330191, 0x0b4b0191, 0x0b670171, 0x0b730171, 0x0b7f0181, + 0x0ba70171, 0x0bbf0181, 0x0bd70161, 0x0bef0181, 0x0bfb0161, 0x0c030181, 0x0c070161, 0x0c130171, + 0x0a150141, 0x0a290131, 0x0a3d0141, 0x0a490141, 0x0a650141, 0x0a910141, 0x0a990141, 0x0ab90141, + 0x0ad30151, 0x0ae70131, 0x0af70131, 0x0b030151, 0x0b2b0141, 0x0b330141, 0x0b4b0151, 0x0b670131, + 0x0b730131, 0x0b7f0131, 0x0ba70141, 0x0bbf0141, 0x0bd70131, 0x0bef0141, 0x0bfb0131, 0x0c030141, + 0x0c070131, 0x0c130131, 0x0a0b0141, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2500 .. 0x25ff */ + 0x052e0111, 0x052f0111, 0x05300111, 0x05310111, 0x05320111, 0x05330111, 0x05340111, 0x05350111, + 0x05360111, 0x05370111, 0x05380111, 0x05390111, 0x053a0111, 0x053b0111, 0x053c0111, 0x053d0111, + 0x053e0111, 0x053f0111, 0x05400111, 0x05410111, 0x05420111, 0x05430111, 0x05440111, 0x05450111, + 0x05460111, 0x05470111, 0x05480111, 0x05490111, 0x054a0111, 0x054b0111, 0x054c0111, 0x054d0111, + 0x054e0111, 0x054f0111, 0x05500111, 0x05510111, 0x05520111, 0x05530111, 0x05540111, 0x05550111, + 0x05560111, 0x05570111, 0x05580111, 0x05590111, 0x055a0111, 0x055b0111, 0x055c0111, 0x055d0111, + 0x055e0111, 0x055f0111, 0x05600111, 0x05610111, 0x05620111, 0x05630111, 0x05640111, 0x05650111, + 0x05660111, 0x05670111, 0x05680111, 0x05690111, 0x056a0111, 0x056b0111, 0x056c0111, 0x056d0111, + 0x056e0111, 0x056f0111, 0x05700111, 0x05710111, 0x05720111, 0x05730111, 0x05740111, 0x05750111, + 0x05760111, 0x05770111, 0x05780111, 0x05790111, 0x057a0111, 0x057b0111, 0x057c0111, 0x057d0111, + 0x057e0111, 0x057f0111, 0x05800111, 0x05810111, 0x05820111, 0x05830111, 0x05840111, 0x05850111, + 0x05860111, 0x05870111, 0x05880111, 0x05890111, 0x058a0111, 0x058b0111, 0x058c0111, 0x058d0111, + 0x058e0111, 0x058f0111, 0x05900111, 0x05910111, 0x05920111, 0x05930111, 0x05940111, 0x05950111, + 0x05960111, 0x05970111, 0x05980111, 0x05990111, 0x059a0111, 0x059b0111, 0x059c0111, 0x059d0111, + 0x059e0111, 0x059f0111, 0x05a00111, 0x05a10111, 0x05a20111, 0x05a30111, 0x05a40111, 0x05a50111, + 0x05a60111, 0x05a70111, 0x05a80111, 0x05a90111, 0x05aa0111, 0x05ab0111, 0x05ac0111, 0x05ad0111, + 0x05ae0111, 0x05af0111, 0x05b00111, 0x05b10111, 0x05b20111, 0x05b30111, 0x05b40111, 0x05b50111, + 0x05b60111, 0x05b70111, 0x05b80111, 0x05b90111, 0x05ba0111, 0x05bb0111, 0x05bc0111, 0x05bd0111, + 0x05be0111, 0x05bf0111, 0x05c00111, 0x05c10111, 0x05c20111, 0x05c30111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x05c40111, 0x05c50111, 0x05c60111, 0x05c70111, 0x05c80111, 0x05c90111, 0x05ca0111, 0x05cb0111, + 0x05cc0111, 0x05cd0111, 0x05ce0111, 0x05cf0111, 0x05d00111, 0x05d10111, 0x05d20111, 0x05d30111, + 0x05d40111, 0x05d50111, 0x05d60111, 0x05d70111, 0x05d80111, 0x05d90111, 0x05da0111, 0x05db0111, + 0x05dc0111, 0x05dd0111, 0x05de0111, 0x05df0111, 0x05e00111, 0x05e10111, 0x05e20111, 0x05e30111, + 0x05e40111, 0x05e50111, 0x05e60111, 0x05e70111, 0x05e80111, 0x05e90111, 0x05ea0111, 0x05eb0111, + 0x05ec0111, 0x05ed0111, 0x05ee0111, 0x05ef0111, 0x05f00111, 0x05f10111, 0x05f20111, 0x05f30111, + 0x05f40111, 0x05f50111, 0x05f60111, 0x05f70111, 0x05f80111, 0x05f90111, 0x05fa0111, 0x05fb0111, + 0x05fc0111, 0x05fd0111, 0x05fe0111, 0x05ff0111, 0x06000111, 0x06010111, 0x06020111, 0x06030111, + 0x06040111, 0x06050111, 0x06060111, 0x06070111, 0x06080111, 0x06090111, 0x060a0111, 0x060b0111, + 0x060c0111, 0x060d0111, 0x060e0111, 0x060f0111, 0x06100111, 0x06110111, 0x06120111, 0x06130111, + 0x06140111, 0x06150111, 0x06160111, 0x06170111, 0x06180111, 0x06190111, 0x061a0111, 0x061b0111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2600 .. 0x26ff */ + 0x061c0111, 0x061d0111, 0x061e0111, 0x061f0111, 0x06200111, 0x06210111, 0x06220111, 0x06230111, + 0x06240111, 0x06250111, 0x06260111, 0x06270111, 0x06280111, 0x06290111, 0x062a0111, 0x062b0111, + 0x062c0111, 0x062d0111, 0x062e0111, 0x062f0111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x06300111, 0x06310111, 0x06320111, 0x06330111, 0x06340111, 0x06350111, 0x06360111, + 0x06370111, 0x06380111, 0x06390111, 0x063a0111, 0x063b0111, 0x063c0111, 0x063d0111, 0x063e0111, + 0x063f0111, 0x06400111, 0x06410111, 0x06420111, 0x06430111, 0x06440111, 0x06450111, 0x06460111, + 0x06470111, 0x06480111, 0x06490111, 0x064a0111, 0x064b0111, 0x064c0111, 0x064d0111, 0x064e0111, + 0x064f0111, 0x06500111, 0x06510111, 0x06520111, 0x06530111, 0x06540111, 0x06550111, 0x06560111, + 0x06570111, 0x06580111, 0x06590111, 0x065a0111, 0x065b0111, 0x065c0111, 0x065d0111, 0x065e0111, + 0x065f0111, 0x06600111, 0x06610111, 0x06620111, 0x06630111, 0x06640111, 0x06650111, 0x06660111, + 0x06670111, 0x06680111, 0x06690111, 0x066a0111, 0x066b0111, 0x066c0111, 0x066d0111, 0x066e0111, + 0x066f0111, 0x06700111, 0x06710111, 0x06720111, 0x06730111, 0x06740111, 0x06750111, 0x06760111, + 0x06770111, 0x06780111, 0x06790111, 0x067a0111, 0x067b0111, 0x067c0111, 0x067d0111, 0x067e0111, + 0x067f0111, 0x06800111, 0x06810111, 0x06820111, 0x06830111, 0x0a080111, 0x0a090111, 0x0a0a0111, + 0x06840111, 0x06850111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2700 .. 0x27ff */ + 0xffffffff, 0x06860111, 0x06870111, 0x06880111, 0x06890111, 0xffffffff, 0x068a0111, 0x068b0111, + 0x068c0111, 0x068d0111, 0xffffffff, 0xffffffff, 0x068e0111, 0x068f0111, 0x06900111, 0x06910111, + 0x06920111, 0x06930111, 0x06940111, 0x06950111, 0x06960111, 0x06970111, 0x06980111, 0x06990111, + 0x069a0111, 0x069b0111, 0x069c0111, 0x069d0111, 0x069e0111, 0x069f0111, 0x06a00111, 0x06a10111, + 0x06a20111, 0x06a30111, 0x06a40111, 0x06a50111, 0x06a60111, 0x06a70111, 0x06a80111, 0x06a90111, + 0xffffffff, 0x06aa0111, 0x06ab0111, 0x06ac0111, 0x06ad0111, 0x06ae0111, 0x06af0111, 0x06b00111, + 0x06b10111, 0x06b20111, 0x06b30111, 0x06b40111, 0x06b50111, 0x06b60111, 0x06b70111, 0x06b80111, + 0x06b90111, 0x06ba0111, 0x06bb0111, 0x06bc0111, 0x06bd0111, 0x06be0111, 0x06bf0111, 0x06c00111, + 0x06c10111, 0x06c20111, 0x06c30111, 0x06c40111, 0x06c50111, 0x06c60111, 0x06c70111, 0x06c80111, + 0x06c90111, 0x06ca0111, 0x06cb0111, 0x06cc0111, 0xffffffff, 0x06cd0111, 0xffffffff, 0x06ce0111, + 0x06cf0111, 0x06d00111, 0x06d10111, 0xffffffff, 0xffffffff, 0xffffffff, 0x06d20111, 0xffffffff, + 0x06d30111, 0x06d40111, 0x06d50111, 0x06d60111, 0x06d70111, 0x06d80111, 0x06d90111, 0xffffffff, + 0xffffffff, 0x06da0111, 0x06db0111, 0x06dc0111, 0x06dd0111, 0x06de0111, 0x06df0111, 0x06e00111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0a0c0141, 0x0a0d0141, + 0x0a0e0141, 0x0a0f0141, 0x0a100141, 0x0a110141, 0x0a120141, 0x0a130141, 0x0a140141, 0x06e10111, + 0x0a0c0141, 0x0a0d0141, 0x0a0e0141, 0x0a0f0141, 0x0a100141, 0x0a110141, 0x0a120141, 0x0a130141, + 0x0a140141, 0x06e20111, 0x0a0c0141, 0x0a0d0141, 0x0a0e0141, 0x0a0f0141, 0x0a100141, 0x0a110141, + 0x0a120141, 0x0a130141, 0x0a140141, 0x06e30111, 0x06e40111, 0xffffffff, 0xffffffff, 0xffffffff, + 0x06e50111, 0x06e60111, 0x06e70111, 0x06e80111, 0x06e90111, 0x06ea0111, 0x06eb0111, 0x06ec0111, + 0x06ed0111, 0x06ee0111, 0x06ef0111, 0x06f00111, 0x06f10111, 0x06f20111, 0x06f30111, 0x06f40111, + 0x06f50111, 0x06f60111, 0x06f70111, 0x06f80111, 0x06f90111, 0x06fa0111, 0x06fb0111, 0x06fc0111, + 0xffffffff, 0x06fd0111, 0x06fe0111, 0x06ff0111, 0x07000111, 0x07010111, 0x07020111, 0x07030111, + 0x07040111, 0x07050111, 0x07060111, 0x07070111, 0x07080111, 0x07090111, 0x070a0111, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2800 .. 0x28ff */ + 0x070b0111, 0x070c0111, 0x070d0111, 0x070e0111, 0x070f0111, 0x07100111, 0x07110111, 0x07120111, + 0x07130111, 0x07140111, 0x07150111, 0x07160111, 0x07170111, 0x07180111, 0x07190111, 0x071a0111, + 0x071b0111, 0x071c0111, 0x071d0111, 0x071e0111, 0x071f0111, 0x07200111, 0x07210111, 0x07220111, + 0x07230111, 0x07240111, 0x07250111, 0x07260111, 0x07270111, 0x07280111, 0x07290111, 0x072a0111, + 0x072b0111, 0x072c0111, 0x072d0111, 0x072e0111, 0x072f0111, 0x07300111, 0x07310111, 0x07320111, + 0x07330111, 0x07340111, 0x07350111, 0x07360111, 0x07370111, 0x07380111, 0x07390111, 0x073a0111, + 0x073b0111, 0x073c0111, 0x073d0111, 0x073e0111, 0x073f0111, 0x07400111, 0x07410111, 0x07420111, + 0x07430111, 0x07440111, 0x07450111, 0x07460111, 0x07470111, 0x07480111, 0x07490111, 0x074a0111, + 0x074b0111, 0x074c0111, 0x074d0111, 0x074e0111, 0x074f0111, 0x07500111, 0x07510111, 0x07520111, + 0x07530111, 0x07540111, 0x07550111, 0x07560111, 0x07570111, 0x07580111, 0x07590111, 0x075a0111, + 0x075b0111, 0x075c0111, 0x075d0111, 0x075e0111, 0x075f0111, 0x07600111, 0x07610111, 0x07620111, + 0x07630111, 0x07640111, 0x07650111, 0x07660111, 0x07670111, 0x07680111, 0x07690111, 0x076a0111, + 0x076b0111, 0x076c0111, 0x076d0111, 0x076e0111, 0x076f0111, 0x07700111, 0x07710111, 0x07720111, + 0x07730111, 0x07740111, 0x07750111, 0x07760111, 0x07770111, 0x07780111, 0x07790111, 0x077a0111, + 0x077b0111, 0x077c0111, 0x077d0111, 0x077e0111, 0x077f0111, 0x07800111, 0x07810111, 0x07820111, + 0x07830111, 0x07840111, 0x07850111, 0x07860111, 0x07870111, 0x07880111, 0x07890111, 0x078a0111, + 0x078b0111, 0x078c0111, 0x078d0111, 0x078e0111, 0x078f0111, 0x07900111, 0x07910111, 0x07920111, + 0x07930111, 0x07940111, 0x07950111, 0x07960111, 0x07970111, 0x07980111, 0x07990111, 0x079a0111, + 0x079b0111, 0x079c0111, 0x079d0111, 0x079e0111, 0x079f0111, 0x07a00111, 0x07a10111, 0x07a20111, + 0x07a30111, 0x07a40111, 0x07a50111, 0x07a60111, 0x07a70111, 0x07a80111, 0x07a90111, 0x07aa0111, + 0x07ab0111, 0x07ac0111, 0x07ad0111, 0x07ae0111, 0x07af0111, 0x07b00111, 0x07b10111, 0x07b20111, + 0x07b30111, 0x07b40111, 0x07b50111, 0x07b60111, 0x07b70111, 0x07b80111, 0x07b90111, 0x07ba0111, + 0x07bb0111, 0x07bc0111, 0x07bd0111, 0x07be0111, 0x07bf0111, 0x07c00111, 0x07c10111, 0x07c20111, + 0x07c30111, 0x07c40111, 0x07c50111, 0x07c60111, 0x07c70111, 0x07c80111, 0x07c90111, 0x07ca0111, + 0x07cb0111, 0x07cc0111, 0x07cd0111, 0x07ce0111, 0x07cf0111, 0x07d00111, 0x07d10111, 0x07d20111, + 0x07d30111, 0x07d40111, 0x07d50111, 0x07d60111, 0x07d70111, 0x07d80111, 0x07d90111, 0x07da0111, + 0x07db0111, 0x07dc0111, 0x07dd0111, 0x07de0111, 0x07df0111, 0x07e00111, 0x07e10111, 0x07e20111, + 0x07e30111, 0x07e40111, 0x07e50111, 0x07e60111, 0x07e70111, 0x07e80111, 0x07e90111, 0x07ea0111, + 0x07eb0111, 0x07ec0111, 0x07ed0111, 0x07ee0111, 0x07ef0111, 0x07f00111, 0x07f10111, 0x07f20111, + 0x07f30111, 0x07f40111, 0x07f50111, 0x07f60111, 0x07f70111, 0x07f80111, 0x07f90111, 0x07fa0111, + 0x07fb0111, 0x07fc0111, 0x07fd0111, 0x07fe0111, 0x07ff0111, 0x08000111, 0x08010111, 0x08020111, + 0x08030111, 0x08040111, 0x08050111, 0x08060111, 0x08070111, 0x08080111, 0x08090111, 0x080a0111, + /* 0x2e00 .. 0x2eff */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xfb400121, 0xfb400121, 0xfb400111, 0xfb400111, 0xfb400121, 0xfb400111, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400111, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400111, + 0xfb400111, 0xfb400121, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400121, 0xfb400111, 0xfb400121, + 0xfb400111, 0xfb400111, 0xffffffff, 0xfb400111, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400121, 0xfb400111, 0xfb400121, + 0xfb400111, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400111, 0xfb400121, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400111, 0xfb410111, 0xfb410111, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410111, 0xfb410121, + 0xfb410121, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410121, + 0xfb410111, 0xfb410111, 0xfb410121, 0xfb410111, 0xfb410111, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410121, 0xfb410111, 0xfb410121, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410121, 0xfb410111, + 0xfb410111, 0xfb410121, 0xfb410111, 0xfb410121, 0xfb410121, 0xfb410111, 0xfb410111, 0xfb410121, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410121, 0xfb410111, 0xfb410121, 0xfb410111, 0xfb410121, + 0xfb410111, 0xfb410121, 0xfb410121, 0xfb410121, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x2f00 .. 0x2fff */ + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, + 0xfb400121, 0xfb400121, 0xfb400121, 0xfb400121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, + 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xfb410121, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x09a90111, 0x09aa0111, 0x09ab0111, 0x09ac0111, 0x09ad0111, 0x09ae0111, 0x09af0111, 0x09b00111, + 0x09b10111, 0x09b20111, 0x09b30111, 0x09b40111, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x3000 .. 0x30ff */ + 0x02090121, 0x02340111, 0x025e0111, 0x02b80111, 0x09b50111, 0x09d70111, 0x192c0111, 0x0a0b0111, + 0x02880111, 0x02890111, 0x028a0111, 0x028b0111, 0x028c0111, 0x028d0111, 0x028e0111, 0x028f0111, + 0x02900111, 0x02910111, 0x09b60111, 0x09b70111, 0x02920111, 0x02930111, 0x02940111, 0x02950111, + 0x02960111, 0x02970111, 0x02980111, 0x02990111, 0x022a0111, 0x02750111, 0x02760111, 0x02770111, + 0x09b80111, 0x0a0c0111, 0x0a0d0111, 0x0a0e0111, 0x0a0f0111, 0x0a100111, 0x0a110111, 0x0a120111, + 0x0a130111, 0x0a140111, 0x0000dc11, 0x0000dd11, 0x0000de11, 0x0000df11, 0x0000e011, 0x0000e111, + 0x022b0111, 0x09d80111, 0x09d80111, 0x09d90111, 0x09d90111, 0x09da0111, 0x09b60121, 0x09b90111, + 0xfb400121, 0xfb400121, 0xfb400121, 0xffffffff, 0xffffffff, 0xffffffff, 0x09ba0111, 0x09bb0111, + 0xffffffff, 0x19210111, 0x19210121, 0x19220111, 0x19220121, 0x19230111, 0x19230121, 0x19240111, + 0x19240121, 0x19250111, 0x19250121, 0x19260111, 0x19260111, 0x19270111, 0x19270111, 0x19280111, + 0x19280111, 0x19290111, 0x19290111, 0x192a0111, 0x192a0111, 0x192b0111, 0x192b0111, 0x192c0121, + 0x192c0121, 0x192d0111, 0x192d0111, 0x192e0111, 0x192e0111, 0x192f0111, 0x192f0111, 0x19300111, + 0x19300111, 0x19310111, 0x19310111, 0x19320111, 0x19320121, 0x19320121, 0x19330111, 0x19330111, + 0x19340111, 0x19340111, 0x19350111, 0x19360111, 0x19370111, 0x19380111, 0x19390111, 0x193a0111, + 0x193a0111, 0x193a0111, 0x193b0111, 0x193b0111, 0x193b0111, 0x193c0111, 0x193c0111, 0x193c0111, + 0x193d0111, 0x193d0111, 0x193d0111, 0x193e0111, 0x193e0111, 0x193e0111, 0x193f0111, 0x19400111, + 0x19410111, 0x19420111, 0x19430111, 0x19440111, 0x19440121, 0x19450111, 0x19450121, 0x19460111, + 0x19460121, 0x19470111, 0x19480111, 0x19490111, 0x194a0111, 0x194b0111, 0x194c0111, 0x194c0121, + 0x194d0111, 0x194e0111, 0x194f0111, 0x19500111, 0x19230121, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x0000e211, 0x0000e311, 0x021e0111, 0x021f0111, 0x09db0111, 0x09db0111, 0xffffffff, + 0xffffffff, 0x19210131, 0x19210151, 0x19220131, 0x19220151, 0x19230131, 0x19230151, 0x19240131, + 0x19240151, 0x19250131, 0x19250151, 0x19260131, 0x19260131, 0x19270121, 0x19270121, 0x19280121, + 0x19280121, 0x19290131, 0x19290131, 0x192a0121, 0x192a0121, 0x192b0121, 0x192b0121, 0x192c0131, + 0x192c0131, 0x192d0121, 0x192d0121, 0x192e0121, 0x192e0121, 0x192f0121, 0x192f0121, 0x19300121, + 0x19300121, 0x19310121, 0x19310121, 0x19320131, 0x19320151, 0x19320151, 0x19330121, 0x19330121, + 0x19340121, 0x19340121, 0x19350121, 0x19360121, 0x19370121, 0x19380121, 0x19390121, 0x193a0121, + 0x193a0121, 0x193a0121, 0x193b0121, 0x193b0121, 0x193b0121, 0x193c0121, 0x193c0121, 0x193c0121, + 0x193d0121, 0x193d0121, 0x193d0121, 0x193e0121, 0x193e0121, 0x193e0121, 0x193f0121, 0x19400121, + 0x19410121, 0x19420121, 0x19430121, 0x19440131, 0x19440151, 0x19450131, 0x19450151, 0x19460131, + 0x19460151, 0x19470121, 0x19480121, 0x19490121, 0x194a0121, 0x194b0121, 0x194c0131, 0x194c0141, + 0x194d0121, 0x194e0121, 0x194f0121, 0x19500121, 0x19230151, 0x19260121, 0x19290121, 0x194c0141, + 0x194d0121, 0x194e0121, 0x194f0121, 0x022c0111, 0x09dc0111, 0x09dd0111, 0x09dd0111, 0xffffffff, + /* 0x3100 .. 0x31ff */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x19510111, 0x19520111, 0x19530111, + 0x19540111, 0x19560111, 0x19570111, 0x19580111, 0x19590111, 0x195a0111, 0x195b0111, 0x195e0111, + 0x195f0111, 0x19600111, 0x19610111, 0x19630111, 0x19640111, 0x19650111, 0x19660111, 0x19670111, + 0x19680111, 0x19690111, 0x196a0111, 0x196b0111, 0x196d0111, 0x196e0111, 0x19700111, 0x19710111, + 0x19720111, 0x19730111, 0x19740111, 0x19750111, 0x19760111, 0x19780111, 0x197c0111, 0x197d0111, + 0x197e0111, 0x197f0111, 0x19550111, 0x195c0111, 0x19620111, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x18310121, 0x18320121, 0x18d10121, 0x18330121, 0x18d30121, 0x18d40121, 0x18340121, + 0x18350121, 0x18360121, 0x18d70121, 0x18d80121, 0x18d90121, 0x18da0121, 0x18db0121, 0x18dc0121, + 0x184b0121, 0x18370121, 0x18380121, 0x18390121, 0x18520121, 0x183a0121, 0x183b0121, 0x183c0121, + 0x183d0121, 0x183e0121, 0x183f0121, 0x18400121, 0x18410121, 0x18420121, 0x18430121, 0x188d0121, + 0x188e0121, 0x188f0121, 0x18900121, 0x18910121, 0x18920121, 0x18930121, 0x18940121, 0x18950121, + 0x18960121, 0x18970121, 0x18980121, 0x18990121, 0x189a0121, 0x189b0121, 0x189c0121, 0x189d0121, + 0x189e0121, 0x189f0121, 0x18a00121, 0x18a10121, 0x188c0121, 0x18450121, 0x18460121, 0x18ee0121, + 0x18ef0121, 0x18f30121, 0x18f50121, 0x18fa0121, 0x18fe0121, 0x19000121, 0x184d0121, 0x19040121, + 0x19060121, 0x184e0121, 0x184f0121, 0x18510121, 0x18530121, 0x18540121, 0x18580121, 0x185a0121, + 0x185c0121, 0x185d0121, 0x185e0121, 0x185f0121, 0x18600121, 0x18630121, 0x18670121, 0x18710121, + 0x18780121, 0x187d0121, 0x19180121, 0x19190121, 0x18880121, 0x18890121, 0x188a0121, 0x18b00121, + 0x18b10121, 0x18b40121, 0x18bd0121, 0x18be0121, 0x18c00121, 0x18ca0121, 0x18cd0121, 0xffffffff, + 0x09bc0111, 0x09bd0111, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, + 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, 0xfb400141, + 0x19510121, 0x19670121, 0x195f0121, 0x195a0121, 0x196f0111, 0x196f0121, 0x196c0111, 0x196b0121, + 0x197e0121, 0x196a0121, 0x197d0121, 0x197e0121, 0x197b0111, 0x195d0111, 0x19700121, 0x19720121, + 0x19790111, 0x197a0111, 0x19770111, 0x197d0131, 0x19520121, 0x19570121, 0x195b0121, 0x195e0121, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0x3200 .. 0x32ff */ + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0xffffffff, 0xffffffff, 0xffffffff, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, + 0x027a0131, 0x027a0131, 0x027a0131, 0x027a0131, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x18310131, 0x18330131, 0x18340131, 0x18360131, 0x18370131, 0x18380131, 0x183a0131, 0x183c0131, + 0x183d0131, 0x183f0131, 0x18400131, 0x18410131, 0x18420131, 0x18430131, 0x18310131, 0x18330131, + 0x18340131, 0x18360131, 0x18370131, 0x18380131, 0x183a0131, 0x183c0131, 0x183d0131, 0x183f0131, + 0x18400131, 0x18410131, 0x18420131, 0x18430131, 0xffffffff, 0xffffffff, 0xffffffff, 0x09be0111, + 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, + 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb410131, 0xfb400131, + 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb410131, 0xfb400131, + 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb410131, 0xfb400131, 0xfb400131, 0xfb400131, + 0xfb410131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, + 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb400131, 0xfb410131, 0xfb400131, + 0xfb400131, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0a0c0131, 0x0a0d0131, 0x0a0e0131, 0x0a0f0131, 0x0a100131, 0x0a110131, 0x0a120131, 0x0a130131, + 0x0a140131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x19210171, 0x19220171, 0x19230171, 0x19240171, 0x19250171, 0x19260151, 0x19270141, 0x19280141, + 0x19290151, 0x192a0141, 0x192b0141, 0x192c0151, 0x192d0141, 0x192e0141, 0x192f0141, 0x19300141, + 0x19310141, 0x19320171, 0x19330141, 0x19340141, 0x19350141, 0x19360141, 0x19370141, 0x19380141, + 0x19390141, 0x193a0141, 0x193b0141, 0x193c0141, 0x193d0141, 0x193e0141, 0x193f0141, 0x19400141, + 0x19410141, 0x19420141, 0x19430141, 0x19440171, 0x19450171, 0x19460171, 0x19470141, 0x19480141, + 0x19490141, 0x194a0141, 0x194b0141, 0x194c0161, 0x194d0131, 0x194e0131, 0x194f0141, 0xffffffff, + /* 0x3300 .. 0x33ff */ + 0x19210181, 0x19210181, 0x19210181, 0x19210181, 0x19220181, 0x19220181, 0x19230181, 0x19240181, + 0x19240181, 0x19250181, 0x19250181, 0x19260161, 0x19260161, 0x19260161, 0x19260161, 0x19260161, + 0x19270151, 0x19270151, 0x19270151, 0x19270151, 0x19270151, 0x19270151, 0x19270151, 0x19270151, + 0x19280151, 0x19280151, 0x19280151, 0x19280151, 0x19290161, 0x192a0151, 0x192a0151, 0x192b0151, + 0x192b0151, 0x192c0161, 0x192e0151, 0x192e0151, 0x19300151, 0x19330151, 0x19340151, 0x19340151, + 0x19350151, 0x19390151, 0x193a0151, 0x193a0151, 0x193a0151, 0x193a0151, 0x193b0151, 0x193b0151, + 0x193b0151, 0x193b0151, 0x193c0151, 0x193c0151, 0x193c0151, 0x193c0151, 0x193d0151, 0x193d0151, + 0x193d0151, 0x193d0151, 0x193d0151, 0x193d0151, 0x193d0151, 0x193e0151, 0x193e0151, 0x193e0151, + 0x193e0151, 0x193e0151, 0x193e0151, 0x193f0151, 0x193f0151, 0x193f0151, 0x193f0151, 0x193f0151, + 0x19400151, 0x19400151, 0x19400151, 0x19420151, 0x19420151, 0x19420151, 0x19440181, 0x19440181, + 0x19450181, 0x19480151, 0x19480151, 0x19490151, 0x19490151, 0x194a0151, 0x194a0151, 0x194c0171, + 0x0a0b0131, 0x0a0c0131, 0x0a0d0131, 0x0a0e0131, 0x0a0f0131, 0x0a100131, 0x0a110131, 0x0a120131, + 0x0a130131, 0x0a140131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, + 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, + 0x0a0d0131, 0x0ab901a1, 0x0a490191, 0x0a1501a1, 0x0a290181, 0x0b4b01b1, 0x0b670181, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfb400151, 0xfb400151, 0xfb400151, 0xfb400151, 0xfb400151, + 0x0b670181, 0x0b3301b1, 0x0c9f0141, 0x0b2b01a1, 0x0af70171, 0x0af70181, 0x0b2b01b1, 0x0a990181, + 0x0a3d01a1, 0x0af70171, 0x0b670181, 0x0b3301b1, 0x0c9f0141, 0x0c9f0141, 0x0b2b01a1, 0x0af70171, + 0x0ab901b1, 0x0af70171, 0x0b2b01b1, 0x0a990181, 0x0bbf01a1, 0x0c9f0141, 0x0b2b01a1, 0x0a490191, + 0x0af70171, 0x0a910191, 0x0b3301b1, 0x0c9f0141, 0x0b2b01a1, 0x0a3d01a1, 0x0af70171, 0x0b2b01a1, + 0x0a3d01a1, 0x0b2b01a1, 0x0af70171, 0x0b2b01a1, 0x0a3d01a1, 0x0b2b01a1, 0x0af70171, 0x0b2b01a1, + 0x0b2b01a1, 0x0b670191, 0x0af70171, 0x0b2b01b1, 0x0a990181, 0x0b7f01a1, 0x0b7f01a1, 0x0b7f01a1, + 0x0b670181, 0x0b3301b1, 0x0c9f0141, 0x0b2b01a1, 0x0b670181, 0x0b3301b1, 0x0c9f0141, 0x0b2b01a1, + 0x0af70171, 0x0b2b01b1, 0x0b670181, 0x0b3301b1, 0x0c9f0141, 0x0b2b01a1, 0x0af70171, 0x0b2b01b1, + 0x0af70171, 0x0b2b01b1, 0x0a150191, 0x0a290191, 0x0a3d01a1, 0x0a3d01a1, 0x0a3d01b1, 0x0a3d01b1, + 0x0a490191, 0x0a990181, 0x0ab901a1, 0x0ab901b1, 0x0ad301b1, 0x0af70181, 0x0af70181, 0x0af70171, + 0x0b0301c1, 0x0b0301c1, 0x0b0301c1, 0x0b0301c1, 0x0b2b01a1, 0x0b2b01a1, 0x0b2b01a1, 0x0b670191, + 0x0b670181, 0x0b670191, 0x0b670191, 0x0ba70191, 0x0ba701a1, 0x0bfb0181, 0xffffffff, 0xffffffff, + 0x0a0c0131, 0x0a0d0131, 0x0a0e0131, 0x0a0f0131, 0x0a100131, 0x0a110131, 0x0a120131, 0x0a130131, + 0x0a140131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, + 0x0a0c0131, 0x0a0c0131, 0x0a0c0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, + 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, 0x0a0d0131, 0x0a0e0131, 0x0a0e0131, 0xffffffff, + /* 0xf900 .. 0xf9ff */ + 0xfb410111, 0xfb400111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb410111, 0xfb410111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb410111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, + 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb410111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb410111, 0xfb400111, + /* 0xfa00 .. 0xfaff */ + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb410111, + 0xfb400111, 0xfb410111, 0xfb400111, 0xfb410111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb400111, + 0xfb400111, 0xfb400111, 0xfb400111, 0xfb400111, 0xfb410111, 0xfb400111, 0xfb400111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, + 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xfb410111, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0xfb00 .. 0xfbff */ + 0x0a910131, 0x0a910131, 0x0a910131, 0x0a910131, 0x0a910131, 0x0ba70131, 0x0ba70131, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0ea30121, 0x0ea30121, 0x0ea30121, 0x0ead0121, 0x0ea30121, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0ec00111, 0x00006711, 0x0ec00121, + 0x0ec60121, 0x0eb70131, 0x0eba0131, 0x0ebb0121, 0x0ec10121, 0x0ec20121, 0x0ec30121, 0x0eca0121, + 0x0ecc0121, 0x039f0131, 0x0ecb0111, 0x0ecb0111, 0x0ecb0111, 0x0ecb0111, 0x0eb70111, 0x0eb70111, + 0x0eb70111, 0x0eb80111, 0x0eb90111, 0x0eba0111, 0x0ebb0111, 0x0ebc0111, 0x0ebd0111, 0xffffffff, + 0x0ebf0111, 0x0ec00111, 0x0ec10131, 0x0ec10111, 0x0ec20111, 0xffffffff, 0x0ec30111, 0xffffffff, + 0x0ec40111, 0x0ec50111, 0xffffffff, 0x0ec70121, 0x0ec70111, 0xffffffff, 0x0ec80111, 0x0ec90111, + 0x0eca0111, 0x0ecb0111, 0x0ecc0111, 0x0ebc0111, 0x0eb80111, 0x0ec10111, 0x0ec70111, 0x0eb70121, + 0x0ed10131, 0x0ed10121, 0x0ed80151, 0x0ed80141, 0x0ed80121, 0x0ed80131, 0x0ed90151, 0x0ed90141, + 0x0ed90121, 0x0ed90131, 0x0eda0151, 0x0eda0141, 0x0eda0121, 0x0eda0131, 0x0edf0151, 0x0edf0141, + 0x0edf0121, 0x0edf0131, 0x0ee20151, 0x0ee20141, 0x0ee20121, 0x0ee20131, 0x0ede0151, 0x0ede0141, + 0x0ede0121, 0x0ede0131, 0x0f1a0151, 0x0f1a0141, 0x0f1a0121, 0x0f1a0131, 0x0f1c0151, 0x0f1c0141, + 0x0f1c0121, 0x0f1c0131, 0x0ee50151, 0x0ee50141, 0x0ee50121, 0x0ee50131, 0x0ee40151, 0x0ee40141, + 0x0ee40121, 0x0ee40131, 0x0ee60151, 0x0ee60141, 0x0ee60121, 0x0ee60131, 0x0ee80151, 0x0ee80141, + 0x0ee80121, 0x0ee80131, 0x0ef50131, 0x0ef50121, 0x0ef40131, 0x0ef40121, 0x0ef60131, 0x0ef60121, + 0x0ef00131, 0x0ef00121, 0x0f020131, 0x0f020121, 0x0efb0131, 0x0efb0121, 0x0f210151, 0x0f210141, + 0x0f210121, 0x0f210131, 0x0f270151, 0x0f270141, 0x0f270121, 0x0f270131, 0x0f2b0151, 0x0f2b0141, + 0x0f2b0121, 0x0f2b0131, 0x0f290151, 0x0f290141, 0x0f290121, 0x0f290131, 0x0f340131, 0x0f340121, + 0x0f350151, 0x0f350141, 0x0f350121, 0x0f350131, 0x0f3d0131, 0x0f3d0121, 0x0f3b0151, 0x0f3b0141, + 0x0f3b0121, 0x0f3b0131, 0x0f3a0151, 0x0f3a0141, 0x0f3a0121, 0x0f3a0131, 0x0f4f0131, 0x0f4f0121, + 0x0f4f0131, 0x0f4f0121, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0f250151, 0x0f250141, 0x0f250121, 0x0f250131, 0x0f420141, + 0x0f420131, 0x0f410131, 0x0f410121, 0x0f430131, 0x0f430121, 0x0f420141, 0x0f460131, 0x0f460121, + 0x0f400131, 0x0f400121, 0x0f440131, 0x0f440121, 0x0f4d0151, 0x0f4d0141, 0x0f4d0121, 0x0f4d0131, + 0x0f480121, 0x0f480131, 0x0ed50151, 0x0ed50141, 0x0ed50151, 0x0ed50141, 0x0ed50151, 0x0ed50141, + 0x0ed50151, 0x0ed50141, 0x0ed50151, 0x0ed50141, 0x0ed50151, 0x0ed50141, 0x0ed50151, 0x0ed50141, + 0x0ed50121, 0x0ed50151, 0x0ed50141, 0x0ed50121, 0x0f4a0151, 0x0f4a0141, 0x0f4a0121, 0x0f4a0131, + /* 0xfc00 .. 0xfcff */ + 0x0ed50151, 0x0ed50151, 0x0ed50151, 0x0ed50151, 0x0ed50151, 0x0ed70151, 0x0ed70151, 0x0ed70151, + 0x0ed70151, 0x0ed70151, 0x0ed70151, 0x0edc0151, 0x0edc0151, 0x0edc0151, 0x0edc0151, 0x0edc0151, + 0x0edc0151, 0x0edd0151, 0x0edd0151, 0x0edd0151, 0x0edd0151, 0x0ee30151, 0x0ee30151, 0x0ee90151, + 0x0ee90151, 0x0eea0151, 0x0eea0151, 0x0eea0151, 0x0f040151, 0x0f040151, 0x0f040151, 0x0f040151, + 0x0f0a0151, 0x0f0a0151, 0x0f0b0151, 0x0f0b0151, 0x0f0b0151, 0x0f0b0151, 0x0f0f0151, 0x0f0f0151, + 0x0f100151, 0x0f120151, 0x0f120151, 0x0f130151, 0x0f130151, 0x0f160151, 0x0f160151, 0x0f160151, + 0x0f160151, 0x0f160151, 0x0f160151, 0x0f1d0151, 0x0f1d0151, 0x0f1d0151, 0x0f1d0151, 0x0f200151, + 0x0f200151, 0x0f200151, 0x0f200151, 0x0f200151, 0x0f200151, 0x0f200151, 0x0f200151, 0x0f2d0151, + 0x0f2d0151, 0x0f2d0151, 0x0f2d0151, 0x0f2d0151, 0x0f2d0151, 0x0f320161, 0x0f320161, 0x0f320161, + 0x0f320161, 0x0f320161, 0x0f320161, 0x0f330151, 0x0f330151, 0x0f330151, 0x0f330151, 0x0f330151, + 0x0f330151, 0x0f390151, 0x0f390151, 0x0f390151, 0x0f390151, 0x0f490161, 0x0f490161, 0x0f490161, + 0x0f490161, 0x0f490161, 0x0f490161, 0x0eef0131, 0x0ef90131, 0x0f480151, 0x00006e31, 0x00006e31, + 0x00006e31, 0x00006e31, 0x00006e31, 0x00006e31, 0x0ed50141, 0x0ed50141, 0x0ed50141, 0x0ed50141, + 0x0ed50141, 0x0ed50141, 0x0ed70141, 0x0ed70141, 0x0ed70141, 0x0ed70141, 0x0ed70141, 0x0ed70141, + 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0edd0141, 0x0edd0141, + 0x0edd0141, 0x0edd0141, 0x0edd0141, 0x0edd0141, 0x0f160141, 0x0f160141, 0x0f1d0141, 0x0f1d0141, + 0x0f200141, 0x0f200141, 0x0f200141, 0x0f200141, 0x0f200141, 0x0f2d0141, 0x0f2d0141, 0x0f2d0141, + 0x0f320151, 0x0f320151, 0x0f330141, 0x0f330141, 0x0f330141, 0x0f330141, 0x0f330141, 0x0f330141, + 0x0f480141, 0x0f490151, 0x0f490151, 0x0f490151, 0x0f490151, 0x0f490151, 0x0f490151, 0x0ed50121, + 0x0ed50121, 0x0ed50121, 0x0ed50121, 0x0ed50121, 0x0ed70121, 0x0ed70121, 0x0ed70121, 0x0ed70121, + 0x0ed70121, 0x0edc0121, 0x0edc0121, 0x0edc0121, 0x0edc0121, 0x0edc0121, 0x0edd0121, 0x0ee30121, + 0x0ee30121, 0x0ee90121, 0x0ee90121, 0x0eea0121, 0x0eea0121, 0x0f040121, 0x0f040121, 0x0f040121, + 0x0f040121, 0x0f0a0121, 0x0f0a0121, 0x0f0a0121, 0x0f0b0121, 0x0f0b0121, 0x0f0b0121, 0x0f0b0121, + 0x0f0f0121, 0x0f100121, 0x0f120121, 0x0f120121, 0x0f130121, 0x0f130121, 0x0f160121, 0x0f160121, + 0x0f160121, 0x0f160121, 0x0f1d0121, 0x0f1d0121, 0x0f200121, 0x0f200121, 0x0f200121, 0x0f200121, + 0x0f200121, 0x0f2d0121, 0x0f2d0121, 0x0f2d0121, 0x0f2d0121, 0x0f2d0121, 0x0f320131, 0x0f320131, + 0x0f320131, 0x0f320131, 0x0f330121, 0x0f330121, 0x0f330121, 0x0f330121, 0x0f330121, 0x0f390121, + 0x0f390121, 0x0f390121, 0x0f490131, 0x0f490131, 0x0f490131, 0x0f490131, 0x0f490131, 0x0ed50131, + 0x0ed50131, 0x0ed70131, 0x0ed70131, 0x0edc0131, 0x0edc0131, 0x0edd0131, 0x0edd0131, 0x0f040131, + 0x0f040131, 0x0f050131, 0x0f050131, 0x0f200131, 0x0f200131, 0x0f2d0131, 0x0f330131, 0x0f330131, + 0x0f490141, 0x0f490141, 0x00006e21, 0x00006e21, 0x00006e21, 0x0f0f0151, 0x0f0f0151, 0x0f120151, + 0x0f120151, 0x0f130151, 0x0f130151, 0x0f040151, 0x0f040151, 0x0f050151, 0x0f050151, 0x0ee90151, + /* 0xfd00 .. 0xfdff */ + 0x0ee90151, 0x0ee30151, 0x0ee30151, 0x0eea0151, 0x0eea0151, 0x0f0a0151, 0x0f0a0151, 0x0f0b0151, + 0x0f0b0151, 0x0f050151, 0x0f050151, 0x0f050151, 0x0f050151, 0x0f050151, 0x0f040151, 0x0f0a0151, + 0x0f0b0151, 0x0f0f0141, 0x0f0f0141, 0x0f120141, 0x0f120141, 0x0f130141, 0x0f130141, 0x0f040141, + 0x0f040141, 0x0f050141, 0x0f050141, 0x0ee90141, 0x0ee90141, 0x0ee30141, 0x0ee30141, 0x0eea0141, + 0x0eea0141, 0x0f0a0141, 0x0f0a0141, 0x0f0b0141, 0x0f0b0141, 0x0f050141, 0x0f050141, 0x0f050141, + 0x0f050141, 0x0f050141, 0x0f040141, 0x0f0a0141, 0x0f0b0141, 0x0f050121, 0x0f050121, 0x0f050121, + 0x0f050121, 0x0f040121, 0x0f050121, 0x0f0f0121, 0x0f040131, 0x0f040131, 0x0f040131, 0x0f050131, + 0x0f050131, 0x0f050131, 0x0f0f0131, 0x0f100131, 0x0ed60131, 0x0ed60141, 0x029a0111, 0x029b0111, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0edc0121, 0x0edc0141, 0x0edc0121, 0x0edc0121, 0x0edc0121, 0x0edc0121, 0x0edc0121, 0x0edc0121, + 0x0ee30141, 0x0ee30121, 0x0ee90141, 0x0ee90141, 0x0f040121, 0x0f040121, 0x0f040141, 0x0f040141, + 0x0f040121, 0x0f040121, 0x0f040141, 0x0f040121, 0x0f0a0141, 0x0f0a0121, 0x0f0a0141, 0x0f050141, + 0x0f050121, 0x0f050141, 0x0f050141, 0x0f050121, 0x0f050141, 0x0f050121, 0x0f0b0141, 0x0f0b0141, + 0x0f0b0121, 0x0f0f0141, 0x0f0f0121, 0x0f0f0121, 0x0f0f0141, 0x0f120141, 0x0f120141, 0x0f120121, + 0x0f120141, 0x0f130141, 0x0f130141, 0x0f130141, 0x0f160141, 0x0f160121, 0x0f1d0141, 0x0f1d0141, + 0x0f2d0141, 0x0f2d0141, 0x0f2d0141, 0x0f2d0121, 0x0f2d0141, 0x0f2d0141, 0x0f2d0121, 0x0f2d0141, + 0x0f2d0121, 0x0f320131, 0x0f320131, 0x0f320151, 0x0f320131, 0x0f320131, 0x0f320131, 0x0f320131, + 0xffffffff, 0xffffffff, 0x0f320131, 0x0f390121, 0x0f390121, 0x0f330121, 0x0f330141, 0x0f330141, + 0x0f330121, 0x0f330141, 0x0f330141, 0x0f330141, 0x0f490151, 0x0f490131, 0x0ed70141, 0x0edc0141, + 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0edc0141, 0x0ee30141, 0x0ee30141, 0x0ee30141, + 0x0f040141, 0x0f0a0141, 0x0f050141, 0x0f0b0141, 0x0f2d0141, 0x0f2d0141, 0x0f490151, 0x0f490151, + 0x0f490151, 0x0f320151, 0x0f1d0141, 0x0f330141, 0x0f1d0121, 0x0f2d0121, 0x0f120141, 0x0f200141, + 0x0f330121, 0x0f320151, 0x0f2d0121, 0x0f200141, 0x0f2d0141, 0x0f330141, 0x0ee30141, 0x0ee90141, + 0x0f320151, 0x0f160141, 0x0ed70141, 0x0f200121, 0x0f120121, 0x0f0a0121, 0x0f040141, 0x0f330141, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x0f0a0151, 0x0f1d0151, 0x0ed60141, 0x0ed60141, 0x0f320161, 0x0f0a0151, 0x0ef90131, 0x0f120151, + 0x0f3e0141, 0x0f0a0151, 0x0f0a0151, 0x0ee30151, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* 0xfe00 .. 0xfeff */ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00005011, 0x00005111, 0x00005211, 0x00005311, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x02550151, 0x02280131, 0x02270121, 0x021b0141, 0x021b0141, 0x027a0171, 0x027b0161, 0x027e0141, + 0x027f0141, 0x02920131, 0x02930131, 0x02900121, 0x02910121, 0x028a0121, 0x028b0121, 0x02880121, + 0x02890121, 0x028c0131, 0x028d0131, 0x028e0121, 0x028f0121, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x02110121, 0x02110121, 0x02110121, 0x02110121, 0x021b0131, 0x021b0131, 0x021b0131, + 0x022d0131, 0x02340121, 0x02550141, 0xffffffff, 0x02350131, 0x02370131, 0x024e0141, 0x024b0141, + 0x02280121, 0x027a0141, 0x027b0131, 0x027e0131, 0x027f0131, 0x02920121, 0x02930121, 0x02a90131, + 0x02a70131, 0x02a20131, 0x039f0141, 0x02210131, 0x03a30131, 0x03a50131, 0x03a40131, 0xffffffff, + 0x02a60131, 0x09e00131, 0x02aa0131, 0x02a10131, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00006831, 0x00006821, 0x00006921, 0xffffffff, 0x00006a21, 0xffffffff, 0x00006b31, 0x00006b21, + 0x00006c31, 0x00006c21, 0x00006d31, 0x00006d21, 0x00006e31, 0x00006e21, 0x00006f31, 0x00006f21, + 0x0ecd0131, 0x0ece0131, 0x0ece0121, 0x0ecf0131, 0x0ecf0121, 0x0ed20131, 0x0ed20121, 0x0ed30131, + 0x0ed30121, 0x0ed50151, 0x0ed50141, 0x0ed50121, 0x0ed50131, 0x0ed60141, 0x0ed60131, 0x0ed70151, + 0x0ed70141, 0x0ed70121, 0x0ed70131, 0x0edb0131, 0x0edb0121, 0x0edc0151, 0x0edc0141, 0x0edc0121, + 0x0edc0131, 0x0edd0151, 0x0edd0141, 0x0edd0121, 0x0edd0131, 0x0ee30151, 0x0ee30141, 0x0ee30121, + 0x0ee30131, 0x0ee90151, 0x0ee90141, 0x0ee90121, 0x0ee90131, 0x0eea0151, 0x0eea0141, 0x0eea0121, + 0x0eea0131, 0x0eee0131, 0x0eee0121, 0x0eef0131, 0x0eef0121, 0x0ef90131, 0x0ef90121, 0x0efa0131, + 0x0efa0121, 0x0f040151, 0x0f040141, 0x0f040121, 0x0f040131, 0x0f050151, 0x0f050141, 0x0f050121, + 0x0f050131, 0x0f0a0151, 0x0f0a0141, 0x0f0a0121, 0x0f0a0131, 0x0f0b0151, 0x0f0b0141, 0x0f0b0121, + 0x0f0b0131, 0x0f0f0151, 0x0f0f0141, 0x0f0f0121, 0x0f0f0131, 0x0f100151, 0x0f100141, 0x0f100121, + 0x0f100131, 0x0f120151, 0x0f120141, 0x0f120121, 0x0f120131, 0x0f130151, 0x0f130141, 0x0f130121, + 0x0f130131, 0x0f160151, 0x0f160141, 0x0f160121, 0x0f160131, 0x0f1d0151, 0x0f1d0141, 0x0f1d0121, + 0x0f1d0131, 0x0f200151, 0x0f200141, 0x0f200121, 0x0f200131, 0x0f2d0151, 0x0f2d0141, 0x0f2d0121, + 0x0f2d0131, 0x0f320161, 0x0f320151, 0x0f320131, 0x0f320141, 0x0f330151, 0x0f330141, 0x0f330121, + 0x0f330131, 0x0f390151, 0x0f390141, 0x0f390121, 0x0f390131, 0x0f3e0141, 0x0f3e0131, 0x0f480151, + 0x0f480141, 0x0f490161, 0x0f490151, 0x0f490131, 0x0f490141, 0x0f2d0151, 0x0f2d0141, 0x0f2d0151, + 0x0f2d0141, 0x0f2d0151, 0x0f2d0141, 0x0f2d0151, 0x0f2d0141, 0xffffffff, 0xffffffff, 0x00000000, + /* 0xff00 .. 0xffff */ + 0xffffffff, 0x024b0121, 0x02700121, 0x02a90121, 0x09e00121, 0x02aa0121, 0x02a70121, 0x02690121, + 0x027a0121, 0x027b0121, 0x02a20121, 0x039f0121, 0x022d0121, 0x02210121, 0x02550121, 0x02a40121, + 0x0a0b0121, 0x0a0c0121, 0x0a0d0121, 0x0a0e0121, 0x0a0f0121, 0x0a100121, 0x0a110121, 0x0a120121, + 0x0a130121, 0x0a140121, 0x02370121, 0x02350121, 0x03a30121, 0x03a40121, 0x03a50121, 0x024e0121, + 0x02a10121, 0x0a150161, 0x0a290151, 0x0a3d0161, 0x0a490161, 0x0a650161, 0x0a910161, 0x0a990161, + 0x0ab90161, 0x0ad30171, 0x0ae70151, 0x0af70151, 0x0b030171, 0x0b2b0161, 0x0b330161, 0x0b4b0171, + 0x0b670151, 0x0b730151, 0x0b7f0151, 0x0ba70161, 0x0bbf0161, 0x0bd70151, 0x0bef0161, 0x0bfb0151, + 0x0c030161, 0x0c070151, 0x0c130151, 0x027c0121, 0x02a60121, 0x027d0121, 0x020f0121, 0x021b0121, + 0x020c0121, 0x0a150121, 0x0a290121, 0x0a3d0121, 0x0a490121, 0x0a650121, 0x0a910121, 0x0a990121, + 0x0ab90121, 0x0ad30121, 0x0ae70121, 0x0af70121, 0x0b030121, 0x0b2b0121, 0x0b330121, 0x0b4b0121, + 0x0b670121, 0x0b730121, 0x0b7f0121, 0x0ba70121, 0x0bbf0121, 0x0bd70121, 0x0bef0121, 0x0bfb0121, + 0x0c030121, 0x0c070121, 0x0c130121, 0x027e0121, 0x03a70121, 0x027f0121, 0x03aa0121, 0xffffffff, + 0xffffffff, 0x025e0121, 0x028c0121, 0x028d0121, 0x02340131, 0x022c0121, 0x194f0131, 0x19210141, + 0x19220141, 0x19230141, 0x19240141, 0x19250141, 0x19440141, 0x19450141, 0x19460141, 0x19320141, + 0x09dc0121, 0x19210161, 0x19220161, 0x19230161, 0x19240161, 0x19250161, 0x19260141, 0x19270131, + 0x19280131, 0x19290141, 0x192a0131, 0x192b0131, 0x192c0141, 0x192d0131, 0x192e0131, 0x192f0131, + 0x19300131, 0x19310131, 0x19320161, 0x19330131, 0x19340131, 0x19350131, 0x19360131, 0x19370131, + 0x19380131, 0x19390131, 0x193a0131, 0x193b0131, 0x193c0131, 0x193d0131, 0x193e0131, 0x193f0131, + 0x19400131, 0x19410131, 0x19420131, 0x19430131, 0x19440161, 0x19450161, 0x19460161, 0x19470131, + 0x19480131, 0x19490131, 0x194a0131, 0x194b0131, 0x194c0151, 0x19500131, 0x0000e221, 0x0000e321, + 0x188c0131, 0x18310141, 0x18320131, 0x18d10131, 0x18330141, 0x18d30131, 0x18d40131, 0x18340141, + 0x18350131, 0x18360141, 0x18d70131, 0x18d80131, 0x18d90131, 0x18da0131, 0x18db0131, 0x18dc0131, + 0x184b0131, 0x18370141, 0x18380141, 0x18390131, 0x18520131, 0x183a0141, 0x183b0131, 0x183c0141, + 0x183d0141, 0x183e0131, 0x183f0141, 0x18400141, 0x18410141, 0x18420141, 0x18430141, 0xffffffff, + 0xffffffff, 0xffffffff, 0x188d0131, 0x188e0131, 0x188f0131, 0x18900131, 0x18910131, 0x18920131, + 0xffffffff, 0xffffffff, 0x18930131, 0x18940131, 0x18950131, 0x18960131, 0x18970131, 0x18980131, + 0xffffffff, 0xffffffff, 0x18990131, 0x189a0131, 0x189b0131, 0x189c0131, 0x189d0131, 0x189e0131, + 0xffffffff, 0xffffffff, 0x189f0131, 0x18a00131, 0x18a10131, 0xffffffff, 0xffffffff, 0xffffffff, + 0x09df0121, 0x09e10121, 0x03a60121, 0x02100121, 0x03a80121, 0x09e20121, 0x09ef0121, 0xffffffff, + 0x05300121, 0x03320121, 0x03340121, 0x03330121, 0x03350121, 0x05c40121, 0x05ef0121, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x09bf0111, 0x09c00111, 0xffffffff, 0xffffffff +}; diff --git a/dll/win32/kernel32/winnls/string/fold.c b/dll/win32/kernel32/winnls/string/fold.c new file mode 100644 index 00000000000..87a4a418faa --- /dev/null +++ b/dll/win32/kernel32/winnls/string/fold.c @@ -0,0 +1,198 @@ +/* + * String folding + * + * Copyright 2003 Jon Griffiths + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/unicode.h" + +static inline WCHAR to_unicode_digit( WCHAR ch ) +{ + extern const WCHAR wine_digitmap[]; + return ch + wine_digitmap[wine_digitmap[ch >> 8] + (ch & 0xff)]; +} + +static inline WCHAR to_unicode_native( WCHAR ch ) +{ + extern const WCHAR wine_compatmap[]; + return ch + wine_compatmap[wine_compatmap[ch >> 8] + (ch & 0xff)]; +} + +static const WCHAR wine_ligatures[] = +{ + 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152, + 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca, + 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc, + 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03, + 0xfb04, 0xfb05, 0xfb06 +}; + +/* Unicode expanded ligatures */ +static const WCHAR wine_expanded_ligatures[][4] = +{ + { 'A','E','\0',1 }, + { 'T','H','\0',1 }, + { 's','s','\0',1 }, + { 'a','e','\0',1 }, + { 't','h','\0',1 }, + { 'I','J','\0',1 }, + { 'i','j','\0',1 }, + { 'O','E','\0',1 }, + { 'o','e','\0',1 }, + { 'D',0x017d,'\0',1 }, + { 'D',0x017e,'\0',1 }, + { 'd',0x017e,'\0',1 }, + { 'L','J','\0',1 }, + { 'L','j','\0',1 }, + { 'l','j','\0',1 }, + { 'N','J','\0',1 }, + { 'N','j','\0',1 }, + { 'n','j','\0',1 }, + { 0x0100,0x0112,'\0',1 }, + { 0x0101,0x0113,'\0',1 }, + { 'D','Z','\0',1 }, + { 'D','z','\0',1 }, + { 'd','z','\0',1 }, + { 0x00c1,0x00c9,'\0',1 }, + { 0x00e1,0x00e9,'\0',1 }, + { 0x05d5,0x05d5,'\0',1 }, + { 0x05d5,0x05d9,'\0',1 }, + { 0x05d9,0x05d9,'\0',1 }, + { 'f','f','\0',1 }, + { 'f','i','\0',1 }, + { 'f','l','\0',1 }, + { 'f','f','i',2 }, + { 'f','f','l',2 }, + { 0x017f,'t','\0',1 }, + { 's','t','\0',1 } +}; + +static inline int get_ligature_len( WCHAR wc ) +{ + int low = 0, high = sizeof(wine_ligatures)/sizeof(WCHAR) -1; + while (low <= high) + { + int pos = (low + high) / 2; + if (wine_ligatures[pos] < wc) + low = pos + 1; + else if (wine_ligatures[pos] > wc) + high = pos - 1; + else + return wine_expanded_ligatures[pos][3]; + } + return 0; +} + +static inline const WCHAR* get_ligature( WCHAR wc ) +{ + static const WCHAR empty_ligature[] = { '\0','\0','\0', 0 }; + int low = 0, high = sizeof(wine_ligatures)/sizeof(WCHAR) -1; + while (low <= high) + { + int pos = (low + high) / 2; + if (wine_ligatures[pos] < wc) + low = pos + 1; + else if (wine_ligatures[pos] > wc) + high = pos - 1; + else + return wine_expanded_ligatures[pos]; + } + return empty_ligature; +} + +/* fold a unicode string */ +int wine_fold_string( int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen ) +{ + WCHAR *dstbase = dst; + const WCHAR *expand; + int i; + + if (srclen == -1) + srclen = strlenW(src) + 1; /* Include terminating NUL in count */ + + if (!dstlen) + { + /* Calculate the required size for dst */ + dstlen = srclen; + + if (flags & MAP_EXPAND_LIGATURES) + { + while (srclen--) + { + dstlen += get_ligature_len(*src); + src++; + } + } + else if (flags & MAP_COMPOSITE) + { + /* FIXME */ + } + else if (flags & MAP_PRECOMPOSED) + { + /* FIXME */ + } + return dstlen; + } + + if (srclen > dstlen) + return 0; + + dstlen -= srclen; + + /* Actually perform the mapping(s) specified */ + for (i = 0; i < srclen; i++) + { + WCHAR ch = *src; + + if (flags & MAP_EXPAND_LIGATURES) + { + expand = get_ligature(ch); + if (expand[0]) + { + if (!dstlen--) + return 0; + dst[0] = expand[0]; + if (expand[2]) + { + if (!dstlen--) + return 0; + *++dst = expand[1]; + ch = expand[2]; + } + else + ch = expand[1]; + dst++; + } + } + else if (flags & MAP_COMPOSITE) + { + /* FIXME */ + } + else if (flags & MAP_PRECOMPOSED) + { + /* FIXME */ + } + if (flags & MAP_FOLDDIGITS) + ch = to_unicode_digit(ch); + if (flags & MAP_FOLDCZONE) + ch = to_unicode_native(ch); + + *dst++ = ch; + src++; + } + return dst - dstbase; +} diff --git a/dll/win32/kernel32/winnls/string/format_msg.c b/dll/win32/kernel32/winnls/string/format_msg.c new file mode 100644 index 00000000000..a79dd5ce744 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/format_msg.c @@ -0,0 +1,597 @@ +/* + * FormatMessage implementation + * + * Copyright 1996 Marcus Meissner + * Copyright 2009 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winternl.h" +#include "winuser.h" +#include "winnls.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +extern HMODULE kernel32_handle; + +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap +WINE_DEFAULT_DEBUG_CHANNEL(resource); + +struct format_args +{ + ULONG_PTR *args; + __ms_va_list *list; + int last; +}; + +/* Messages used by FormatMessage + * + * They can be specified either directly or using a message ID and + * loading them from the resource. + * + * The resourcedata has following format: + * start: + * 0: DWORD nrofentries + * nrofentries * subentry: + * 0: DWORD firstentry + * 4: DWORD lastentry + * 8: DWORD offset from start to the stringentries + * + * (lastentry-firstentry) * stringentry: + * 0: WORD len (0 marks end) [ includes the 4 byte header length ] + * 2: WORD flags + * 4: CHAR[len-4] + * (stringentry i of a subentry refers to the ID 'firstentry+i') + * + * Yes, ANSI strings in win32 resources. Go figure. + */ + +static const WCHAR PCNTFMTWSTR[] = { '%','%','%','s',0 }; +static const WCHAR FMTWSTR[] = { '%','s',0 }; + +/********************************************************************** + * load_message (internal) + */ +static LPWSTR load_message( HMODULE module, UINT id, WORD lang ) +{ + const MESSAGE_RESOURCE_ENTRY *mre; + WCHAR *buffer; + NTSTATUS status; + + TRACE("module = %p, id = %08x\n", module, id ); + + if (!module) module = GetModuleHandleW( NULL ); + if ((status = RtlFindMessage( module, (ULONG)RT_MESSAGETABLE, lang, id, &mre )) != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return NULL; + } + + if (mre->Flags & MESSAGE_RESOURCE_UNICODE) + { + int len = (strlenW( (const WCHAR *)mre->Text ) + 1) * sizeof(WCHAR); + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len ))) return NULL; + memcpy( buffer, mre->Text, len ); + } + else + { + int len = MultiByteToWideChar( CP_ACP, 0, (const char *)mre->Text, -1, NULL, 0 ); + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; + MultiByteToWideChar( CP_ACP, 0, (const char*)mre->Text, -1, buffer, len ); + } + TRACE("returning %s\n", wine_dbgstr_w(buffer)); + return buffer; +} + +/********************************************************************** + * get_arg (internal) + */ +static ULONG_PTR get_arg( int nr, DWORD flags, struct format_args *args ) +{ + if (nr == -1) nr = args->last + 1; + if (args->list) + { + if (!args->args) args->args = HeapAlloc( GetProcessHeap(), 0, 99 * sizeof(ULONG_PTR) ); + while (nr > args->last) + args->args[args->last++] = va_arg( *args->list, ULONG_PTR ); + } + if (nr > args->last) args->last = nr; + return args->args[nr - 1]; +} + +/********************************************************************** + * format_insert (internal) + */ +static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format, + DWORD flags, struct format_args *args, + LPWSTR *result ) +{ + static const WCHAR fmt_lu[] = {'%','l','u',0}; + WCHAR *wstring = NULL, *p, fmt[256]; + ULONG_PTR arg; + int size; + + if (*format != '!') /* simple string */ + { + arg = get_arg( insert, flags, args ); + if (unicode_caller) + { + WCHAR *str = (WCHAR *)arg; + *result = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR) ); + strcpyW( *result, str ); + } + else + { + char *str = (char *)arg; + DWORD length = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + *result = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, str, -1, *result, length ); + } + return format; + } + + format++; + p = fmt; + *p++ = '%'; + + while (*format == '0' || + *format == '+' || + *format == '-' || + *format == ' ' || + *format == '*' || + *format == '#') + { + if (*format == '*') + { + p += sprintfW( p, fmt_lu, get_arg( insert, flags, args )); + insert = -1; + format++; + } + else *p++ = *format++; + } + while (isdigitW(*format)) *p++ = *format++; + + if (*format == '.') + { + *p++ = *format++; + if (*format == '*') + { + p += sprintfW( p, fmt_lu, get_arg( insert, flags, args )); + insert = -1; + format++; + } + else + while (isdigitW(*format)) *p++ = *format++; + } + + /* replicate MS bug: drop an argument when using va_list with width/precision */ + if (insert == -1 && args->list) args->last--; + arg = get_arg( insert, flags, args ); + + /* check for ascii string format */ + if ((format[0] == 'h' && format[1] == 's') || + (format[0] == 'h' && format[1] == 'S') || + (unicode_caller && format[0] == 'S') || + (!unicode_caller && format[0] == 's')) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, (char *)arg, -1, NULL, 0 ); + wstring = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, (char *)arg, -1, wstring, len ); + arg = (ULONG_PTR)wstring; + *p++ = 's'; + } + /* check for ascii character format */ + else if ((format[0] == 'h' && format[1] == 'c') || + (format[0] == 'h' && format[1] == 'C') || + (unicode_caller && format[0] == 'C') || + (!unicode_caller && format[0] == 'c')) + { + char ch = arg; + wstring = HeapAlloc( GetProcessHeap(), 0, 2 * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, &ch, 1, wstring, 1 ); + wstring[1] = 0; + arg = (ULONG_PTR)wstring; + *p++ = 's'; + } + /* check for wide string format */ + else if ((format[0] == 'l' && format[1] == 's') || + (format[0] == 'l' && format[1] == 'S') || + (format[0] == 'w' && format[1] == 's') || + (!unicode_caller && format[0] == 'S')) + { + *p++ = 's'; + } + /* check for wide character format */ + else if ((format[0] == 'l' && format[1] == 'c') || + (format[0] == 'l' && format[1] == 'C') || + (format[0] == 'w' && format[1] == 'c') || + (!unicode_caller && format[0] == 'C')) + { + *p++ = 'c'; + } + /* FIXME: handle I64 etc. */ + else while (*format && *format != '!') *p++ = *format++; + + *p = 0; + size = 256; + for (;;) + { + WCHAR *ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); + int needed = snprintfW( ret, size, fmt, arg ); + if (needed == -1 || needed >= size) + { + HeapFree( GetProcessHeap(), 0, ret ); + size = max( needed + 1, size * 2 ); + } + else + { + *result = ret; + break; + } + } + + while (*format && *format != '!') format++; + if (*format == '!') format++; + + HeapFree( GetProcessHeap(), 0, wstring ); + return format; +} + +/********************************************************************** + * format_message (internal) + */ +static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr, + struct format_args *format_args ) +{ + LPWSTR target,t; + DWORD talloced; + LPCWSTR f; + DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK; + BOOL eos = FALSE; + WCHAR ch; + + target = t = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 * sizeof(WCHAR) ); + talloced = 100; + +#define ADD_TO_T(c) do {\ + *t++=c;\ + if ((DWORD)(t-target) == talloced) {\ + target = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2*sizeof(WCHAR));\ + t = target+talloced;\ + talloced*=2;\ + } \ +} while (0) + + f = fmtstr; + while (*f && !eos) { + if (*f=='%') { + int insertnr; + WCHAR *str,*x; + + f++; + switch (*f) { + case '1':case '2':case '3':case '4':case '5': + case '6':case '7':case '8':case '9': + if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) + goto ignore_inserts; + else if (((dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->args) || + (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->list)) + { + SetLastError(ERROR_INVALID_PARAMETER); + HeapFree(GetProcessHeap(), 0, target); + return NULL; + } + insertnr = *f-'0'; + switch (f[1]) { + case '0':case '1':case '2':case '3': + case '4':case '5':case '6':case '7': + case '8':case '9': + f++; + insertnr = insertnr*10 + *f-'0'; + f++; + break; + default: + f++; + break; + } + f = format_insert( unicode_caller, insertnr, f, dwFlags, format_args, &str ); + for (x = str; *x; x++) ADD_TO_T(*x); + HeapFree( GetProcessHeap(), 0, str ); + break; + case 'n': + ADD_TO_T('\r'); + ADD_TO_T('\n'); + f++; + break; + case 'r': + ADD_TO_T('\r'); + f++; + break; + case 't': + ADD_TO_T('\t'); + f++; + break; + case '0': + eos = TRUE; + f++; + break; + case '\0': + SetLastError(ERROR_INVALID_PARAMETER); + HeapFree(GetProcessHeap(), 0, target); + return NULL; + ignore_inserts: + default: + if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) + ADD_TO_T('%'); + ADD_TO_T(*f++); + break; + } + } else { + ch = *f; + f++; + if (ch == '\r') { + if (*f == '\n') + f++; + if(width) + ADD_TO_T(' '); + else + { + ADD_TO_T('\r'); + ADD_TO_T('\n'); + } + } else { + if (ch == '\n') + { + if(width) + ADD_TO_T(' '); + else + { + ADD_TO_T('\r'); + ADD_TO_T('\n'); + } + } + else + ADD_TO_T(ch); + } + } + } + *t = '\0'; + + return target; +} +#undef ADD_TO_T + +/*********************************************************************** + * FormatMessageA (KERNEL32.@) + * FIXME: missing wrap, + */ +DWORD WINAPI FormatMessageA( + DWORD dwFlags, + LPCVOID lpSource, + DWORD dwMessageId, + DWORD dwLanguageId, + LPSTR lpBuffer, + DWORD nSize, + __ms_va_list* args ) +{ + struct format_args format_args; + DWORD ret = 0; + LPWSTR target; + DWORD destlength; + LPWSTR from; + DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK; + + TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n", + dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); + + if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + if (!lpBuffer) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + else + *(LPSTR *)lpBuffer = NULL; + } + + if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) + { + format_args.args = (ULONG_PTR *)args; + format_args.list = NULL; + format_args.last = 0; + } + else + { + format_args.args = NULL; + format_args.list = args; + format_args.last = 0; + } + + if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) + FIXME("line wrapping (%u) not supported.\n", width); + from = NULL; + if (dwFlags & FORMAT_MESSAGE_FROM_STRING) + { + DWORD length = MultiByteToWideChar(CP_ACP, 0, lpSource, -1, NULL, 0); + from = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) ); + MultiByteToWideChar(CP_ACP, 0, lpSource, -1, from, length); + } + else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM)) + { + if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) + from = load_message( (HMODULE)lpSource, dwMessageId, dwLanguageId ); + if (!from && (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)) + from = load_message( kernel32_handle, dwMessageId, dwLanguageId ); + if (!from) return 0; + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + target = format_message( FALSE, dwFlags, from, &format_args ); + if (!target) + goto failure; + + TRACE("-- %s\n", debugstr_w(target)); + + /* Only try writing to an output buffer if there are processed characters + * in the temporary output buffer. */ + if (*target) + { + destlength = WideCharToMultiByte(CP_ACP, 0, target, -1, NULL, 0, NULL, NULL); + if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + LPSTR buf = LocalAlloc(LMEM_ZEROINIT, max(nSize, destlength)); + WideCharToMultiByte(CP_ACP, 0, target, -1, buf, destlength, NULL, NULL); + *((LPSTR*)lpBuffer) = buf; + } + else + { + if (nSize < destlength) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto failure; + } + WideCharToMultiByte(CP_ACP, 0, target, -1, lpBuffer, destlength, NULL, NULL); + } + ret = destlength - 1; /* null terminator */ + } + +failure: + HeapFree(GetProcessHeap(),0,target); + HeapFree(GetProcessHeap(),0,from); + if (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)) HeapFree( GetProcessHeap(), 0, format_args.args ); + TRACE("-- returning %u\n", ret); + return ret; +} + +/*********************************************************************** + * FormatMessageW (KERNEL32.@) + */ +DWORD WINAPI FormatMessageW( + DWORD dwFlags, + LPCVOID lpSource, + DWORD dwMessageId, + DWORD dwLanguageId, + LPWSTR lpBuffer, + DWORD nSize, + __ms_va_list* args ) +{ + struct format_args format_args; + DWORD ret = 0; + LPWSTR target; + DWORD talloced; + LPWSTR from; + DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK; + + TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n", + dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); + + if (!lpBuffer) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + *(LPWSTR *)lpBuffer = NULL; + + if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) + { + format_args.args = (ULONG_PTR *)args; + format_args.list = NULL; + format_args.last = 0; + } + else + { + format_args.args = NULL; + format_args.list = args; + format_args.last = 0; + } + + if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) + FIXME("line wrapping not supported.\n"); + from = NULL; + if (dwFlags & FORMAT_MESSAGE_FROM_STRING) { + from = HeapAlloc( GetProcessHeap(), 0, (strlenW(lpSource) + 1) * + sizeof(WCHAR) ); + strcpyW( from, lpSource ); + } + else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM)) + { + if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) + from = load_message( (HMODULE)lpSource, dwMessageId, dwLanguageId ); + if (!from && (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)) + from = load_message( kernel32_handle, dwMessageId, dwLanguageId ); + if (!from) return 0; + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + target = format_message( TRUE, dwFlags, from, &format_args ); + if (!target) + goto failure; + + talloced = strlenW(target)+1; + TRACE("-- %s\n",debugstr_w(target)); + + /* Only allocate a buffer if there are processed characters in the + * temporary output buffer. If a caller supplies the buffer, then + * a null terminator will be written to it. */ + if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + if (*target) + { + /* nSize is the MINIMUM size */ + *((LPVOID*)lpBuffer) = LocalAlloc(LMEM_ZEROINIT, max(nSize, talloced)*sizeof(WCHAR)); + strcpyW(*(LPWSTR*)lpBuffer, target); + } + } + else + { + if (nSize < talloced) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto failure; + } + strcpyW(lpBuffer, target); + } + + ret = talloced - 1; /* null terminator */ +failure: + HeapFree(GetProcessHeap(),0,target); + HeapFree(GetProcessHeap(),0,from); + if (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)) HeapFree( GetProcessHeap(), 0, format_args.args ); + TRACE("-- returning %u\n", ret); + return ret; +} diff --git a/dll/win32/kernel32/winnls/string/lang.c b/dll/win32/kernel32/winnls/string/lang.c new file mode 100644 index 00000000000..198a4067e5a --- /dev/null +++ b/dll/win32/kernel32/winnls/string/lang.c @@ -0,0 +1,2709 @@ +/* + * Locale support + * + * Copyright 1995 Martin von Loewis + * Copyright 1998 David Lee Lambert + * Copyright 2000 Julio César G√°zquez + * Copyright 2002 Alexandre Julliard for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//#include "config.h" +//#include "wine/port.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winuser.h" /* for RT_STRINGW */ +#include "winternl.h" +#include "wine/unicode.h" +#include "winnls.h" +#include "winerror.h" +#include "winver.h" +#include "wine/debug.h" + +#include "lcformat_private.h" +#define REG_SZ 1 +extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen); +extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen); +extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2); +static inline unsigned short get_char_typeW( WCHAR ch ) +{ + extern const unsigned short wine_wctype_table[]; + return wine_wctype_table[wine_wctype_table[ch >> 8] + (ch & 0xff)]; +} + +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap +WINE_DEFAULT_DEBUG_CHANNEL(nls); + +extern HMODULE kernel32_handle; + +#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|\ + LOCALE_RETURN_NUMBER|LOCALE_RETURN_GENITIVE_NAMES) + +static const WCHAR szNlsKeyName[] = { + 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\','N','l','s','\0' +}; + +static const WCHAR szLocaleKeyName[] = { + 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\','N','l','s','\\','L','o','c','a','l','e',0 +}; + +static const WCHAR szLangGroupsKeyName[] = { + 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\','N','l','s','\\', + 'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0 +}; + +/* Charset to codepage map, sorted by name. */ +static const struct charset_entry +{ + const char *charset_name; + UINT codepage; +} charset_names[] = +{ + { "BIG5", 950 }, + { "CP1250", 1250 }, + { "CP1251", 1251 }, + { "CP1252", 1252 }, + { "CP1253", 1253 }, + { "CP1254", 1254 }, + { "CP1255", 1255 }, + { "CP1256", 1256 }, + { "CP1257", 1257 }, + { "CP1258", 1258 }, + { "CP932", 932 }, + { "CP936", 936 }, + { "CP949", 949 }, + { "CP950", 950 }, + { "EUCJP", 20932 }, + { "GB2312", 936 }, + { "IBM037", 37 }, + { "IBM1026", 1026 }, + { "IBM424", 424 }, + { "IBM437", 437 }, + { "IBM500", 500 }, + { "IBM850", 850 }, + { "IBM852", 852 }, + { "IBM855", 855 }, + { "IBM857", 857 }, + { "IBM860", 860 }, + { "IBM861", 861 }, + { "IBM862", 862 }, + { "IBM863", 863 }, + { "IBM864", 864 }, + { "IBM865", 865 }, + { "IBM866", 866 }, + { "IBM869", 869 }, + { "IBM874", 874 }, + { "IBM875", 875 }, + { "ISO88591", 28591 }, + { "ISO885910", 28600 }, + { "ISO885913", 28603 }, + { "ISO885914", 28604 }, + { "ISO885915", 28605 }, + { "ISO885916", 28606 }, + { "ISO88592", 28592 }, + { "ISO88593", 28593 }, + { "ISO88594", 28594 }, + { "ISO88595", 28595 }, + { "ISO88596", 28596 }, + { "ISO88597", 28597 }, + { "ISO88598", 28598 }, + { "ISO88599", 28599 }, + { "KOI8R", 20866 }, + { "KOI8U", 21866 }, + { "UTF8", CP_UTF8 } +}; + + +struct locale_name +{ + WCHAR win_name[128]; /* Windows name ("en-US") */ + WCHAR lang[128]; /* language ("en") (note: buffer contains the other strings too) */ + WCHAR *country; /* country ("US") */ + WCHAR *charset; /* charset ("UTF-8") for Unix format only */ + WCHAR *script; /* script ("Latn") for Windows format only */ + WCHAR *modifier; /* modifier or sort order */ + LCID lcid; /* corresponding LCID */ + int matches; /* number of elements matching LCID (0..4) */ + UINT codepage; /* codepage corresponding to charset */ +}; + +/* locale ids corresponding to the various Unix locale parameters */ +static LCID lcid_LC_COLLATE; +static LCID lcid_LC_CTYPE; +static LCID lcid_LC_MONETARY; +static LCID lcid_LC_NUMERIC; +static LCID lcid_LC_TIME; +static LCID lcid_LC_PAPER; +static LCID lcid_LC_MEASUREMENT; +static LCID lcid_LC_TELEPHONE; + +/* Copy Ascii string to Unicode without using codepages */ +static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n ) +{ + while (n > 1 && *src) + { + *dst++ = (unsigned char)*src++; + n--; + } + if (n) *dst = 0; +} + + +/*********************************************************************** + * get_lcid_codepage + * + * Retrieve the ANSI codepage for a given locale. + */ +static inline UINT get_lcid_codepage( LCID lcid ) +{ + UINT ret; + if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret, + sizeof(ret)/sizeof(WCHAR) )) ret = 0; + return ret; +} + +/*********************************************************************** + * convert_default_lcid + * + * Get the default LCID to use for a given lctype in GetLocaleInfo. + */ +static LCID convert_default_lcid( LCID lcid, LCTYPE lctype ) +{ + if (lcid == LOCALE_SYSTEM_DEFAULT || + lcid == LOCALE_USER_DEFAULT || + lcid == LOCALE_NEUTRAL) + { + LCID default_id = 0; + + switch(lctype & 0xffff) + { + case LOCALE_SSORTNAME: + default_id = lcid_LC_COLLATE; + break; + + case LOCALE_FONTSIGNATURE: + case LOCALE_IDEFAULTANSICODEPAGE: + case LOCALE_IDEFAULTCODEPAGE: + case LOCALE_IDEFAULTEBCDICCODEPAGE: + case LOCALE_IDEFAULTMACCODEPAGE: + case LOCALE_IDEFAULTUNIXCODEPAGE: + default_id = lcid_LC_CTYPE; + break; + + case LOCALE_ICURRDIGITS: + case LOCALE_ICURRENCY: + case LOCALE_IINTLCURRDIGITS: + case LOCALE_INEGCURR: + case LOCALE_INEGSEPBYSPACE: + case LOCALE_INEGSIGNPOSN: + case LOCALE_INEGSYMPRECEDES: + case LOCALE_IPOSSEPBYSPACE: + case LOCALE_IPOSSIGNPOSN: + case LOCALE_IPOSSYMPRECEDES: + case LOCALE_SCURRENCY: + case LOCALE_SINTLSYMBOL: + case LOCALE_SMONDECIMALSEP: + case LOCALE_SMONGROUPING: + case LOCALE_SMONTHOUSANDSEP: + case LOCALE_SNATIVECURRNAME: + default_id = lcid_LC_MONETARY; + break; + + case LOCALE_IDIGITS: + case LOCALE_IDIGITSUBSTITUTION: + case LOCALE_ILZERO: + case LOCALE_INEGNUMBER: + case LOCALE_SDECIMAL: + case LOCALE_SGROUPING: + //case LOCALE_SNAN: + case LOCALE_SNATIVEDIGITS: + case LOCALE_SNEGATIVESIGN: + //case LOCALE_SNEGINFINITY: + //case LOCALE_SPOSINFINITY: + case LOCALE_SPOSITIVESIGN: + case LOCALE_STHOUSAND: + default_id = lcid_LC_NUMERIC; + break; + + case LOCALE_ICALENDARTYPE: + case LOCALE_ICENTURY: + case LOCALE_IDATE: + case LOCALE_IDAYLZERO: + case LOCALE_IFIRSTDAYOFWEEK: + case LOCALE_IFIRSTWEEKOFYEAR: + case LOCALE_ILDATE: + case LOCALE_IMONLZERO: + case LOCALE_IOPTIONALCALENDAR: + case LOCALE_ITIME: + case LOCALE_ITIMEMARKPOSN: + case LOCALE_ITLZERO: + case LOCALE_S1159: + case LOCALE_S2359: + case LOCALE_SABBREVDAYNAME1: + case LOCALE_SABBREVDAYNAME2: + case LOCALE_SABBREVDAYNAME3: + case LOCALE_SABBREVDAYNAME4: + case LOCALE_SABBREVDAYNAME5: + case LOCALE_SABBREVDAYNAME6: + case LOCALE_SABBREVDAYNAME7: + case LOCALE_SABBREVMONTHNAME1: + case LOCALE_SABBREVMONTHNAME2: + case LOCALE_SABBREVMONTHNAME3: + case LOCALE_SABBREVMONTHNAME4: + case LOCALE_SABBREVMONTHNAME5: + case LOCALE_SABBREVMONTHNAME6: + case LOCALE_SABBREVMONTHNAME7: + case LOCALE_SABBREVMONTHNAME8: + case LOCALE_SABBREVMONTHNAME9: + case LOCALE_SABBREVMONTHNAME10: + case LOCALE_SABBREVMONTHNAME11: + case LOCALE_SABBREVMONTHNAME12: + case LOCALE_SABBREVMONTHNAME13: + case LOCALE_SDATE: + case LOCALE_SDAYNAME1: + case LOCALE_SDAYNAME2: + case LOCALE_SDAYNAME3: + case LOCALE_SDAYNAME4: + case LOCALE_SDAYNAME5: + case LOCALE_SDAYNAME6: + case LOCALE_SDAYNAME7: + //case LOCALE_SDURATION: + case LOCALE_SLONGDATE: + case LOCALE_SMONTHNAME1: + case LOCALE_SMONTHNAME2: + case LOCALE_SMONTHNAME3: + case LOCALE_SMONTHNAME4: + case LOCALE_SMONTHNAME5: + case LOCALE_SMONTHNAME6: + case LOCALE_SMONTHNAME7: + case LOCALE_SMONTHNAME8: + case LOCALE_SMONTHNAME9: + case LOCALE_SMONTHNAME10: + case LOCALE_SMONTHNAME11: + case LOCALE_SMONTHNAME12: + case LOCALE_SMONTHNAME13: + case LOCALE_SSHORTDATE: + //case LOCALE_SSHORTESTDAYNAME1: + //case LOCALE_SSHORTESTDAYNAME2: + //case LOCALE_SSHORTESTDAYNAME3: + //case LOCALE_SSHORTESTDAYNAME4: + //case LOCALE_SSHORTESTDAYNAME5: + //case LOCALE_SSHORTESTDAYNAME6: + //case LOCALE_SSHORTESTDAYNAME7: + case LOCALE_STIME: + case LOCALE_STIMEFORMAT: + case LOCALE_SYEARMONTH: + default_id = lcid_LC_TIME; + break; + + case LOCALE_IPAPERSIZE: + default_id = lcid_LC_PAPER; + break; + + case LOCALE_IMEASURE: + default_id = lcid_LC_MEASUREMENT; + break; + + case LOCALE_ICOUNTRY: + default_id = lcid_LC_TELEPHONE; + break; + } + if (default_id) lcid = default_id; + } + return ConvertDefaultLocale( lcid ); +} + +/*********************************************************************** + * is_genitive_name_supported + * + * Determine could LCTYPE basically support genitive name form or not. + */ +static BOOL is_genitive_name_supported( LCTYPE lctype ) +{ + switch(lctype & 0xffff) + { + case LOCALE_SMONTHNAME1: + case LOCALE_SMONTHNAME2: + case LOCALE_SMONTHNAME3: + case LOCALE_SMONTHNAME4: + case LOCALE_SMONTHNAME5: + case LOCALE_SMONTHNAME6: + case LOCALE_SMONTHNAME7: + case LOCALE_SMONTHNAME8: + case LOCALE_SMONTHNAME9: + case LOCALE_SMONTHNAME10: + case LOCALE_SMONTHNAME11: + case LOCALE_SMONTHNAME12: + case LOCALE_SMONTHNAME13: + return TRUE; + default: + return FALSE; + } +} + +/*********************************************************************** + * create_registry_key + * + * Create the Control Panel\\International registry key. + */ +static inline HANDLE create_registry_key(void) +{ + static const WCHAR cplW[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l',0}; + static const WCHAR intlW[] = {'I','n','t','e','r','n','a','t','i','o','n','a','l',0}; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + HANDLE cpl_key, hkey = 0; + + if (RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey ) != STATUS_SUCCESS) return 0; + + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, cplW ); + + if (!NtCreateKey( &cpl_key, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) + { + NtClose( attr.RootDirectory ); + attr.RootDirectory = cpl_key; + RtlInitUnicodeString( &nameW, intlW ); + if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) hkey = 0; + } + NtClose( attr.RootDirectory ); + return hkey; +} + +/*********************************************************************** + * GetUserDefaultLangID (KERNEL32.@) + * + * Get the default language Id for the current user. + * + * PARAMS + * None. + * + * RETURNS + * The current LANGID of the default language for the current user. + */ +LANGID WINAPI GetUserDefaultLangID(void) +{ + return LANGIDFROMLCID(GetUserDefaultLCID()); +} + + +/*********************************************************************** + * GetSystemDefaultLangID (KERNEL32.@) + * + * Get the default language Id for the system. + * + * PARAMS + * None. + * + * RETURNS + * The current LANGID of the default language for the system. + */ +LANGID WINAPI GetSystemDefaultLangID(void) +{ + return LANGIDFROMLCID(GetSystemDefaultLCID()); +} + + +/*********************************************************************** + * GetUserDefaultLCID (KERNEL32.@) + * + * Get the default locale Id for the current user. + * + * PARAMS + * None. + * + * RETURNS + * The current LCID of the default locale for the current user. + */ +LCID WINAPI GetUserDefaultLCID(void) +{ + LCID lcid; + NtQueryDefaultLocale( TRUE, &lcid ); + return lcid; +} + + +/*********************************************************************** + * GetSystemDefaultLCID (KERNEL32.@) + * + * Get the default locale Id for the system. + * + * PARAMS + * None. + * + * RETURNS + * The current LCID of the default locale for the system. + */ +LCID WINAPI GetSystemDefaultLCID(void) +{ + LCID lcid; + NtQueryDefaultLocale( FALSE, &lcid ); + return lcid; +} + + +/*********************************************************************** + * GetUserDefaultUILanguage (KERNEL32.@) + * + * Get the default user interface language Id for the current user. + * + * PARAMS + * None. + * + * RETURNS + * The current LANGID of the default UI language for the current user. + */ +LANGID WINAPI GetUserDefaultUILanguage(void) +{ + LANGID lang; + NtQueryDefaultUILanguage( &lang ); + return lang; +} + + +/*********************************************************************** + * GetSystemDefaultUILanguage (KERNEL32.@) + * + * Get the default user interface language Id for the system. + * + * PARAMS + * None. + * + * RETURNS + * The current LANGID of the default UI language for the system. This is + * typically the same language used during the installation process. + */ +LANGID WINAPI GetSystemDefaultUILanguage(void) +{ + LANGID lang; + NtQueryInstallUILanguage( &lang ); + return lang; +} + +/****************************************************************************** + * get_locale_value_name + * + * Gets the registry value name for a given lctype. + */ +static const WCHAR *get_locale_value_name( DWORD lctype ) +{ + static const WCHAR iCalendarTypeW[] = {'i','C','a','l','e','n','d','a','r','T','y','p','e',0}; + static const WCHAR iCountryW[] = {'i','C','o','u','n','t','r','y',0}; + static const WCHAR iCurrDigitsW[] = {'i','C','u','r','r','D','i','g','i','t','s',0}; + static const WCHAR iCurrencyW[] = {'i','C','u','r','r','e','n','c','y',0}; + static const WCHAR iDateW[] = {'i','D','a','t','e',0}; + static const WCHAR iDigitsW[] = {'i','D','i','g','i','t','s',0}; + static const WCHAR iFirstDayOfWeekW[] = {'i','F','i','r','s','t','D','a','y','O','f','W','e','e','k',0}; + static const WCHAR iFirstWeekOfYearW[] = {'i','F','i','r','s','t','W','e','e','k','O','f','Y','e','a','r',0}; + static const WCHAR iLDateW[] = {'i','L','D','a','t','e',0}; + static const WCHAR iLZeroW[] = {'i','L','Z','e','r','o',0}; + static const WCHAR iMeasureW[] = {'i','M','e','a','s','u','r','e',0}; + static const WCHAR iNegCurrW[] = {'i','N','e','g','C','u','r','r',0}; + static const WCHAR iNegNumberW[] = {'i','N','e','g','N','u','m','b','e','r',0}; + static const WCHAR iPaperSizeW[] = {'i','P','a','p','e','r','S','i','z','e',0}; + static const WCHAR iTLZeroW[] = {'i','T','L','Z','e','r','o',0}; + static const WCHAR iTimePrefixW[] = {'i','T','i','m','e','P','r','e','f','i','x',0}; + static const WCHAR iTimeW[] = {'i','T','i','m','e',0}; + static const WCHAR s1159W[] = {'s','1','1','5','9',0}; + static const WCHAR s2359W[] = {'s','2','3','5','9',0}; + static const WCHAR sCountryW[] = {'s','C','o','u','n','t','r','y',0}; + static const WCHAR sCurrencyW[] = {'s','C','u','r','r','e','n','c','y',0}; + static const WCHAR sDateW[] = {'s','D','a','t','e',0}; + static const WCHAR sDecimalW[] = {'s','D','e','c','i','m','a','l',0}; + static const WCHAR sGroupingW[] = {'s','G','r','o','u','p','i','n','g',0}; + static const WCHAR sLanguageW[] = {'s','L','a','n','g','u','a','g','e',0}; + static const WCHAR sListW[] = {'s','L','i','s','t',0}; + static const WCHAR sLongDateW[] = {'s','L','o','n','g','D','a','t','e',0}; + static const WCHAR sMonDecimalSepW[] = {'s','M','o','n','D','e','c','i','m','a','l','S','e','p',0}; + static const WCHAR sMonGroupingW[] = {'s','M','o','n','G','r','o','u','p','i','n','g',0}; + static const WCHAR sMonThousandSepW[] = {'s','M','o','n','T','h','o','u','s','a','n','d','S','e','p',0}; + static const WCHAR sNativeDigitsW[] = {'s','N','a','t','i','v','e','D','i','g','i','t','s',0}; + static const WCHAR sNegativeSignW[] = {'s','N','e','g','a','t','i','v','e','S','i','g','n',0}; + static const WCHAR sPositiveSignW[] = {'s','P','o','s','i','t','i','v','e','S','i','g','n',0}; + static const WCHAR sShortDateW[] = {'s','S','h','o','r','t','D','a','t','e',0}; + static const WCHAR sThousandW[] = {'s','T','h','o','u','s','a','n','d',0}; + static const WCHAR sTimeFormatW[] = {'s','T','i','m','e','F','o','r','m','a','t',0}; + static const WCHAR sTimeW[] = {'s','T','i','m','e',0}; + static const WCHAR sYearMonthW[] = {'s','Y','e','a','r','M','o','n','t','h',0}; + static const WCHAR NumShapeW[] = {'N','u','m','s','h','a','p','e',0}; + + switch (lctype) + { + /* These values are used by SetLocaleInfo and GetLocaleInfo, and + * the values are stored in the registry, confirmed under Windows. + */ + case LOCALE_ICALENDARTYPE: return iCalendarTypeW; + case LOCALE_ICURRDIGITS: return iCurrDigitsW; + case LOCALE_ICURRENCY: return iCurrencyW; + case LOCALE_IDIGITS: return iDigitsW; + case LOCALE_IFIRSTDAYOFWEEK: return iFirstDayOfWeekW; + case LOCALE_IFIRSTWEEKOFYEAR: return iFirstWeekOfYearW; + case LOCALE_ILZERO: return iLZeroW; + case LOCALE_IMEASURE: return iMeasureW; + case LOCALE_INEGCURR: return iNegCurrW; + case LOCALE_INEGNUMBER: return iNegNumberW; + case LOCALE_IPAPERSIZE: return iPaperSizeW; + case LOCALE_ITIME: return iTimeW; + case LOCALE_S1159: return s1159W; + case LOCALE_S2359: return s2359W; + case LOCALE_SCURRENCY: return sCurrencyW; + case LOCALE_SDATE: return sDateW; + case LOCALE_SDECIMAL: return sDecimalW; + case LOCALE_SGROUPING: return sGroupingW; + case LOCALE_SLIST: return sListW; + case LOCALE_SLONGDATE: return sLongDateW; + case LOCALE_SMONDECIMALSEP: return sMonDecimalSepW; + case LOCALE_SMONGROUPING: return sMonGroupingW; + case LOCALE_SMONTHOUSANDSEP: return sMonThousandSepW; + case LOCALE_SNEGATIVESIGN: return sNegativeSignW; + case LOCALE_SPOSITIVESIGN: return sPositiveSignW; + case LOCALE_SSHORTDATE: return sShortDateW; + case LOCALE_STHOUSAND: return sThousandW; + case LOCALE_STIME: return sTimeW; + case LOCALE_STIMEFORMAT: return sTimeFormatW; + case LOCALE_SYEARMONTH: return sYearMonthW; + + /* The following are not listed under MSDN as supported, + * but seem to be used and also stored in the registry. + */ + case LOCALE_ICOUNTRY: return iCountryW; + case LOCALE_IDATE: return iDateW; + case LOCALE_ILDATE: return iLDateW; + case LOCALE_ITLZERO: return iTLZeroW; + case LOCALE_SCOUNTRY: return sCountryW; + case LOCALE_SABBREVLANGNAME: return sLanguageW; + + /* The following are used in XP and later */ + case LOCALE_IDIGITSUBSTITUTION: return NumShapeW; + case LOCALE_SNATIVEDIGITS: return sNativeDigitsW; + case LOCALE_ITIMEMARKPOSN: return iTimePrefixW; + } + return NULL; +} + + +/****************************************************************************** + * get_registry_locale_info + * + * Retrieve user-modified locale info from the registry. + * Return length, 0 on error, -1 if not found. + */ +static INT get_registry_locale_info( LPCWSTR value, LPWSTR buffer, INT len ) +{ + DWORD size; + INT ret; + HANDLE hkey; + NTSTATUS status; + UNICODE_STRING nameW; + KEY_VALUE_PARTIAL_INFORMATION *info; + static const int info_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); + + if (!(hkey = create_registry_key())) return -1; + + RtlInitUnicodeString( &nameW, value ); + size = info_size + len * sizeof(WCHAR); + + if (!(info = HeapAlloc( GetProcessHeap(), 0, size ))) + { + NtClose( hkey ); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return 0; + } + + status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info, size, &size ); + + if (!status) + { + ret = (size - info_size) / sizeof(WCHAR); + /* append terminating null if needed */ + if (!ret || ((WCHAR *)info->Data)[ret-1]) + { + if (ret < len || !buffer) ret++; + else + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ret = 0; + } + } + if (ret && buffer) + { + memcpy( buffer, info->Data, (ret-1) * sizeof(WCHAR) ); + buffer[ret-1] = 0; + } + } + else if (status == STATUS_BUFFER_OVERFLOW && !buffer) + { + ret = (size - info_size) / sizeof(WCHAR) + 1; + } + else if (status == STATUS_OBJECT_NAME_NOT_FOUND) + { + ret = -1; + } + else + { + SetLastError( RtlNtStatusToDosError(status) ); + ret = 0; + } + NtClose( hkey ); + HeapFree( GetProcessHeap(), 0, info ); + return ret; +} + + +/****************************************************************************** + * GetLocaleInfoA (KERNEL32.@) + * + * Get information about an aspect of a locale. + * + * PARAMS + * lcid [I] LCID of the locale + * lctype [I] LCTYPE_ flags from "winnls.h" + * buffer [O] Destination for the information + * len [I] Length of buffer in characters + * + * RETURNS + * Success: The size of the data requested. If buffer is non-NULL, it is filled + * with the information. + * Failure: 0. Use GetLastError() to determine the cause. + * + * NOTES + * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT + * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE, + * which is a bit string. + */ +INT WINAPI GetLocaleInfoA( LCID lcid, LCTYPE lctype, LPSTR buffer, INT len ) +{ + WCHAR *bufferW; + INT lenW, ret; + + TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len ); + + if (len < 0 || (len && !buffer)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + if (lctype & LOCALE_RETURN_GENITIVE_NAMES ) + { + SetLastError( ERROR_INVALID_FLAGS ); + return 0; + } + + if (!len) buffer = NULL; + + if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0; + + if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return 0; + } + if ((ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW ))) + { + if ((lctype & LOCALE_RETURN_NUMBER) || + ((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_FONTSIGNATURE)) + { + /* it's not an ASCII string, just bytes */ + ret *= sizeof(WCHAR); + if (buffer) + { + if (ret <= len) memcpy( buffer, bufferW, ret ); + else + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ret = 0; + } + } + } + else + { + UINT codepage = CP_ACP; + if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid ); + ret = WideCharToMultiByte( codepage, 0, bufferW, ret, buffer, len, NULL, NULL ); + } + } + HeapFree( GetProcessHeap(), 0, bufferW ); + return ret; +} + + +/****************************************************************************** + * GetLocaleInfoW (KERNEL32.@) + * + * See GetLocaleInfoA. + */ +INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len ) +{ + LANGID lang_id; + HRSRC hrsrc; + HGLOBAL hmem; + INT ret; + UINT lcflags; + const WCHAR *p; + unsigned int i; + + if (len < 0 || (len && !buffer)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + if (lctype & LOCALE_RETURN_GENITIVE_NAMES && + !is_genitive_name_supported( lctype )) + { + SetLastError( ERROR_INVALID_FLAGS ); + return 0; + } + + if (!len) buffer = NULL; + + lcid = convert_default_lcid( lcid, lctype ); + + lcflags = lctype & LOCALE_LOCALEINFOFLAGSMASK; + lctype &= 0xffff; + + TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len ); + + /* first check for overrides in the registry */ + + if (!(lcflags & LOCALE_NOUSEROVERRIDE) && + lcid == convert_default_lcid( LOCALE_USER_DEFAULT, lctype )) + { + const WCHAR *value = get_locale_value_name(lctype); + + if (value) + { + if (lcflags & LOCALE_RETURN_NUMBER) + { + WCHAR tmp[16]; + ret = get_registry_locale_info( value, tmp, sizeof(tmp)/sizeof(WCHAR) ); + if (ret > 0) + { + WCHAR *end; + UINT number = strtolW( tmp, &end, 10 ); + if (*end) /* invalid number */ + { + SetLastError( ERROR_INVALID_FLAGS ); + return 0; + } + ret = sizeof(UINT)/sizeof(WCHAR); + if (!buffer) return ret; + if (ret > len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return 0; + } + memcpy( buffer, &number, sizeof(number) ); + } + } + else ret = get_registry_locale_info( value, buffer, len ); + + if (ret != -1) return ret; + } + } + + /* now load it from kernel resources */ + + lang_id = LANGIDFROMLCID( lcid ); + + /* replace SUBLANG_NEUTRAL by SUBLANG_DEFAULT */ + if (SUBLANGID(lang_id) == SUBLANG_NEUTRAL) + lang_id = MAKELANGID(PRIMARYLANGID(lang_id), SUBLANG_DEFAULT); + + if (!(hrsrc = FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, + ULongToPtr((lctype >> 4) + 1), lang_id ))) + { + SetLastError( ERROR_INVALID_FLAGS ); /* no such lctype */ + return 0; + } + if (!(hmem = LoadResource( kernel32_handle, hrsrc ))) + return 0; + + p = LockResource( hmem ); + for (i = 0; i < (lctype & 0x0f); i++) p += *p + 1; + + if (lcflags & LOCALE_RETURN_NUMBER) ret = sizeof(UINT)/sizeof(WCHAR); + else if (is_genitive_name_supported( lctype ) && *p) + { + /* genitive form's stored after a null separator from a nominative */ + for (i = 1; i <= *p; i++) if (!p[i]) break; + + if (i <= *p && (lcflags & LOCALE_RETURN_GENITIVE_NAMES)) + { + ret = *p - i + 1; + p += i; + } + else ret = i; + } + else + ret = (lctype == LOCALE_FONTSIGNATURE) ? *p : *p + 1; + + if (!buffer) return ret; + + if (ret > len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return 0; + } + + if (lcflags & LOCALE_RETURN_NUMBER) + { + UINT number; + WCHAR *end, *tmp = HeapAlloc( GetProcessHeap(), 0, (*p + 1) * sizeof(WCHAR) ); + if (!tmp) return 0; + memcpy( tmp, p + 1, *p * sizeof(WCHAR) ); + tmp[*p] = 0; + number = strtolW( tmp, &end, 10 ); + if (!*end) + memcpy( buffer, &number, sizeof(number) ); + else /* invalid number */ + { + SetLastError( ERROR_INVALID_FLAGS ); + ret = 0; + } + HeapFree( GetProcessHeap(), 0, tmp ); + + TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d) returning number %d\n", + lcid, lctype, buffer, len, number ); + } + else + { + memcpy( buffer, p + 1, ret * sizeof(WCHAR) ); + if (lctype != LOCALE_FONTSIGNATURE) buffer[ret-1] = 0; + + TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d) returning %d %s\n", + lcid, lctype, buffer, len, ret, debugstr_w(buffer) ); + } + return ret; +} + + +/****************************************************************************** + * SetLocaleInfoA [KERNEL32.@] + * + * Set information about an aspect of a locale. + * + * PARAMS + * lcid [I] LCID of the locale + * lctype [I] LCTYPE_ flags from "winnls.h" + * data [I] Information to set + * + * RETURNS + * Success: TRUE. The information given will be returned by GetLocaleInfoA() + * whenever it is called without LOCALE_NOUSEROVERRIDE. + * Failure: FALSE. Use GetLastError() to determine the cause. + * + * NOTES + * - Values are only be set for the current user locale; the system locale + * settings cannot be changed. + * - Any settings changed by this call are lost when the locale is changed by + * the control panel (in Wine, this happens every time you change LANG). + * - The native implementation of this function does not check that lcid matches + * the current user locale, and simply sets the new values. Wine warns you in + * this case, but behaves the same. + */ +BOOL WINAPI SetLocaleInfoA(LCID lcid, LCTYPE lctype, LPCSTR data) +{ + UINT codepage = CP_ACP; + WCHAR *strW; + DWORD len; + BOOL ret; + + if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid ); + + if (!data) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + len = MultiByteToWideChar( codepage, 0, data, -1, NULL, 0 ); + if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + MultiByteToWideChar( codepage, 0, data, -1, strW, len ); + ret = SetLocaleInfoW( lcid, lctype, strW ); + HeapFree( GetProcessHeap(), 0, strW ); + return ret; +} + + +/****************************************************************************** + * SetLocaleInfoW (KERNEL32.@) + * + * See SetLocaleInfoA. + */ +BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data ) +{ + const WCHAR *value; + static const WCHAR intlW[] = {'i','n','t','l',0 }; + UNICODE_STRING valueW; + NTSTATUS status; + HANDLE hkey; + + lctype &= 0xffff; + value = get_locale_value_name( lctype ); + + if (!data || !value) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (lctype == LOCALE_IDATE || lctype == LOCALE_ILDATE) + { + SetLastError( ERROR_INVALID_FLAGS ); + return FALSE; + } + + TRACE("setting %x (%s) to %s\n", lctype, debugstr_w(value), debugstr_w(data) ); + + /* FIXME: should check that data to set is sane */ + + /* FIXME: profile functions should map to registry */ + WriteProfileStringW( intlW, value, data ); + + if (!(hkey = create_registry_key())) return FALSE; + RtlInitUnicodeString( &valueW, value ); + status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, data, (strlenW(data)+1)*sizeof(WCHAR) ); + + if (lctype == LOCALE_SSHORTDATE || lctype == LOCALE_SLONGDATE) + { + /* Set I-value from S value */ + WCHAR *lpD, *lpM, *lpY; + WCHAR szBuff[2]; + + lpD = strrchrW(data, 'd'); + lpM = strrchrW(data, 'M'); + lpY = strrchrW(data, 'y'); + + if (lpD <= lpM) + { + szBuff[0] = '1'; /* D-M-Y */ + } + else + { + if (lpY <= lpM) + szBuff[0] = '2'; /* Y-M-D */ + else + szBuff[0] = '0'; /* M-D-Y */ + } + + szBuff[1] = '\0'; + + if (lctype == LOCALE_SSHORTDATE) + lctype = LOCALE_IDATE; + else + lctype = LOCALE_ILDATE; + + value = get_locale_value_name( lctype ); + + WriteProfileStringW( intlW, value, szBuff ); + + RtlInitUnicodeString( &valueW, value ); + status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, szBuff, sizeof(szBuff) ); + } + + NtClose( hkey ); + + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + +/*********************************************************************** + * GetThreadLocale (KERNEL32.@) + * + * Get the current threads locale. + * + * PARAMS + * None. + * + * RETURNS + * The LCID currently associated with the calling thread. + */ +LCID WINAPI GetThreadLocale(void) +{ + LCID ret = NtCurrentTeb()->CurrentLocale; + if (!ret) NtCurrentTeb()->CurrentLocale = ret = GetUserDefaultLCID(); + return ret; +} + +/********************************************************************** + * SetThreadLocale (KERNEL32.@) + * + * Set the current threads locale. + * + * PARAMS + * lcid [I] LCID of the locale to set + * + * RETURNS + * Success: TRUE. The threads locale is set to lcid. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI SetThreadLocale( LCID lcid ) +{ + TRACE("(0x%04X)\n", lcid); + + lcid = ConvertDefaultLocale(lcid); + + if (lcid != GetThreadLocale()) + { + if (!IsValidLocale(lcid, LCID_SUPPORTED)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + NtCurrentTeb()->CurrentLocale = lcid; + } + return TRUE; +} + +/****************************************************************************** + * ConvertDefaultLocale (KERNEL32.@) + * + * Convert a default locale identifier into a real identifier. + * + * PARAMS + * lcid [I] LCID identifier of the locale to convert + * + * RETURNS + * lcid unchanged, if not a default locale or its sublanguage is + * not SUBLANG_NEUTRAL. + * GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT. + * GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL. + * Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT. + */ +LCID WINAPI ConvertDefaultLocale( LCID lcid ) +{ + LANGID langid; + + switch (lcid) + { + case LOCALE_SYSTEM_DEFAULT: + lcid = GetSystemDefaultLCID(); + break; + case LOCALE_USER_DEFAULT: + case LOCALE_NEUTRAL: + lcid = GetUserDefaultLCID(); + break; + default: + /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */ + langid = LANGIDFROMLCID(lcid); + if (SUBLANGID(langid) == SUBLANG_NEUTRAL) + { + langid = MAKELANGID(PRIMARYLANGID(langid), SUBLANG_DEFAULT); + lcid = MAKELCID(langid, SORTIDFROMLCID(lcid)); + } + } + return lcid; +} + + +/****************************************************************************** + * IsValidLocale (KERNEL32.@) + * + * Determine if a locale is valid. + * + * PARAMS + * lcid [I] LCID of the locale to check + * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system + * + * RETURNS + * TRUE, if lcid is valid, + * FALSE, otherwise. + * + * NOTES + * Wine does not currently make the distinction between supported and installed. All + * languages supported are installed by default. + */ +BOOL WINAPI IsValidLocale( LCID lcid, DWORD flags ) +{ + /* check if language is registered in the kernel32 resources */ + return FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, + (LPCWSTR)LOCALE_ILANGUAGE, LANGIDFROMLCID(lcid)) != 0; +} + + +static BOOL CALLBACK enum_lang_proc_a( HMODULE hModule, LPCSTR type, + LPCSTR name, WORD LangID, LONG_PTR lParam ) +{ + LOCALE_ENUMPROCA lpfnLocaleEnum = (LOCALE_ENUMPROCA)lParam; + char buf[20]; + + sprintf(buf, "%08x", (UINT)LangID); + return lpfnLocaleEnum( buf ); +} + +static BOOL CALLBACK enum_lang_proc_w( HMODULE hModule, LPCWSTR type, + LPCWSTR name, WORD LangID, LONG_PTR lParam ) +{ + static const WCHAR formatW[] = {'%','0','8','x',0}; + LOCALE_ENUMPROCW lpfnLocaleEnum = (LOCALE_ENUMPROCW)lParam; + WCHAR buf[20]; + sprintfW( buf, formatW, (UINT)LangID ); + return lpfnLocaleEnum( buf ); +} + +/****************************************************************************** + * EnumSystemLocalesA (KERNEL32.@) + * + * Call a users function for each locale available on the system. + * + * PARAMS + * lpfnLocaleEnum [I] Callback function to call for each locale + * dwFlags [I] LOCALE_SUPPORTED=All supported, LOCALE_INSTALLED=Installed only + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI EnumSystemLocalesA( LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags ) +{ + TRACE("(%p,%08x)\n", lpfnLocaleEnum, dwFlags); + EnumResourceLanguagesA( kernel32_handle, (LPSTR)RT_STRING, + (LPCSTR)LOCALE_ILANGUAGE, enum_lang_proc_a, + (LONG_PTR)lpfnLocaleEnum); + return TRUE; +} + + +/****************************************************************************** + * EnumSystemLocalesW (KERNEL32.@) + * + * See EnumSystemLocalesA. + */ +BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags ) +{ + TRACE("(%p,%08x)\n", lpfnLocaleEnum, dwFlags); + EnumResourceLanguagesW( kernel32_handle, (LPWSTR)RT_STRING, + (LPCWSTR)LOCALE_ILANGUAGE, enum_lang_proc_w, + (LONG_PTR)lpfnLocaleEnum); + return TRUE; +} + +/*********************************************************************** + * VerLanguageNameA (KERNEL32.@) + * + * Get the name of a language. + * + * PARAMS + * wLang [I] LANGID of the language + * szLang [O] Destination for the language name + * + * RETURNS + * Success: The size of the language name. If szLang is non-NULL, it is filled + * with the name. + * Failure: 0. Use GetLastError() to determine the cause. + * + */ +DWORD WINAPI VerLanguageNameA( DWORD wLang, LPSTR szLang, DWORD nSize ) +{ + return GetLocaleInfoA( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize ); +} + + +/*********************************************************************** + * VerLanguageNameW (KERNEL32.@) + * + * See VerLanguageNameA. + */ +DWORD WINAPI VerLanguageNameW( DWORD wLang, LPWSTR szLang, DWORD nSize ) +{ + return GetLocaleInfoW( MAKELCID(wLang, SORT_DEFAULT), LOCALE_SENGLANGUAGE, szLang, nSize ); +} + +/****************************************************************************** + * GetStringTypeW (KERNEL32.@) + * + * See GetStringTypeA. + */ +BOOL WINAPI GetStringTypeW( DWORD type, LPCWSTR src, INT count, LPWORD chartype ) +{ + static const unsigned char type2_map[16] = + { + C2_NOTAPPLICABLE, /* unassigned */ + C2_LEFTTORIGHT, /* L */ + C2_RIGHTTOLEFT, /* R */ + C2_EUROPENUMBER, /* EN */ + C2_EUROPESEPARATOR, /* ES */ + C2_EUROPETERMINATOR, /* ET */ + C2_ARABICNUMBER, /* AN */ + C2_COMMONSEPARATOR, /* CS */ + C2_BLOCKSEPARATOR, /* B */ + C2_SEGMENTSEPARATOR, /* S */ + C2_WHITESPACE, /* WS */ + C2_OTHERNEUTRAL, /* ON */ + C2_RIGHTTOLEFT, /* AL */ + C2_NOTAPPLICABLE, /* NSM */ + C2_NOTAPPLICABLE, /* BN */ + C2_OTHERNEUTRAL /* LRE, LRO, RLE, RLO, PDF */ + }; + + if (count == -1) count = strlenW(src) + 1; + switch(type) + { + case CT_CTYPE1: + while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff; + break; + case CT_CTYPE2: + while (count--) *chartype++ = type2_map[get_char_typeW( *src++ ) >> 12]; + break; + case CT_CTYPE3: + { + WARN("CT_CTYPE3: semi-stub.\n"); + while (count--) + { + int c = *src; + WORD type1, type3 = 0; /* C3_NOTAPPLICABLE */ + + type1 = get_char_typeW( *src++ ) & 0xfff; + /* try to construct type3 from type1 */ + if(type1 & C1_SPACE) type3 |= C3_SYMBOL; + if(type1 & C1_ALPHA) type3 |= C3_ALPHA; + if ((c>=0x30A0)&&(c<=0x30FF)) type3 |= C3_KATAKANA; + if ((c>=0x3040)&&(c<=0x309F)) type3 |= C3_HIRAGANA; + if ((c>=0x4E00)&&(c<=0x9FAF)) type3 |= C3_IDEOGRAPH; + if ((c>=0x0600)&&(c<=0x06FF)) type3 |= C3_KASHIDA; + if ((c>=0x3000)&&(c<=0x303F)) type3 |= C3_SYMBOL; + + if ((c>=0xFF00)&&(c<=0xFF60)) type3 |= C3_FULLWIDTH; + if ((c>=0xFF00)&&(c<=0xFF20)) type3 |= C3_SYMBOL; + if ((c>=0xFF3B)&&(c<=0xFF40)) type3 |= C3_SYMBOL; + if ((c>=0xFF5B)&&(c<=0xFF60)) type3 |= C3_SYMBOL; + if ((c>=0xFF21)&&(c<=0xFF3A)) type3 |= C3_ALPHA; + if ((c>=0xFF41)&&(c<=0xFF5A)) type3 |= C3_ALPHA; + if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_FULLWIDTH; + if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_SYMBOL; + + if ((c>=0xFF61)&&(c<=0xFFDC)) type3 |= C3_HALFWIDTH; + if ((c>=0xFF61)&&(c<=0xFF64)) type3 |= C3_SYMBOL; + if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_KATAKANA; + if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_ALPHA; + if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_HALFWIDTH; + if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_SYMBOL; + *chartype++ = type3; + } + break; + } + default: + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + return TRUE; +} + + +/****************************************************************************** + * GetStringTypeExW (KERNEL32.@) + * + * See GetStringTypeExA. + */ +BOOL WINAPI GetStringTypeExW( LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype ) +{ + /* locale is ignored for Unicode */ + return GetStringTypeW( type, src, count, chartype ); +} + + +/****************************************************************************** + * GetStringTypeA (KERNEL32.@) + * + * Get characteristics of the characters making up a string. + * + * PARAMS + * locale [I] Locale Id for the string + * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info + * src [I] String to analyse + * count [I] Length of src in chars, or -1 if src is NUL terminated + * chartype [O] Destination for the calculated characteristics + * + * RETURNS + * Success: TRUE. chartype is filled with the requested characteristics of each char + * in src. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI GetStringTypeA( LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype ) +{ + UINT cp; + INT countW; + LPWSTR srcW; + BOOL ret = FALSE; + + if(count == -1) count = strlen(src) + 1; + + if (!(cp = get_lcid_codepage( locale ))) + { + FIXME("For locale %04x using current ANSI code page\n", locale); + cp = GetACP(); + } + + countW = MultiByteToWideChar(cp, 0, src, count, NULL, 0); + if((srcW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR)))) + { + MultiByteToWideChar(cp, 0, src, count, srcW, countW); + /* + * NOTE: the target buffer has 1 word for each CHARACTER in the source + * string, with multibyte characters there maybe be more bytes in count + * than character space in the buffer! + */ + ret = GetStringTypeW(type, srcW, countW, chartype); + HeapFree(GetProcessHeap(), 0, srcW); + } + return ret; +} + +/****************************************************************************** + * GetStringTypeExA (KERNEL32.@) + * + * Get characteristics of the characters making up a string. + * + * PARAMS + * locale [I] Locale Id for the string + * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info + * src [I] String to analyse + * count [I] Length of src in chars, or -1 if src is NUL terminated + * chartype [O] Destination for the calculated characteristics + * + * RETURNS + * Success: TRUE. chartype is filled with the requested characteristics of each char + * in src. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI GetStringTypeExA( LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype ) +{ + return GetStringTypeA(locale, type, src, count, chartype); +} + + +/************************************************************************* + * LCMapStringW (KERNEL32.@) + * + * See LCMapStringA. + */ +INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, + LPWSTR dst, INT dstlen) +{ + LPWSTR dst_ptr; + + if (!src || !srclen || dstlen < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + /* mutually exclusive flags */ + if ((flags & (LCMAP_LOWERCASE | LCMAP_UPPERCASE)) == (LCMAP_LOWERCASE | LCMAP_UPPERCASE) || + (flags & (LCMAP_HIRAGANA | LCMAP_KATAKANA)) == (LCMAP_HIRAGANA | LCMAP_KATAKANA) || + (flags & (LCMAP_HALFWIDTH | LCMAP_FULLWIDTH)) == (LCMAP_HALFWIDTH | LCMAP_FULLWIDTH) || + (flags & (LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE)) == (LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE)) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + if (!dstlen) dst = NULL; + + lcid = ConvertDefaultLocale(lcid); + + if (flags & LCMAP_SORTKEY) + { + INT ret; + if (src == dst) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + if (srclen < 0) srclen = strlenW(src); + + TRACE("(0x%04x,0x%08x,%s,%d,%p,%d)\n", + lcid, flags, debugstr_wn(src, srclen), srclen, dst, dstlen); + + ret = wine_get_sortkey(flags, src, srclen, (char *)dst, dstlen); + if (ret == 0) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + else + ret++; + return ret; + } + + /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */ + if (flags & SORT_STRINGSORT) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + if (srclen < 0) srclen = strlenW(src) + 1; + + TRACE("(0x%04x,0x%08x,%s,%d,%p,%d)\n", + lcid, flags, debugstr_wn(src, srclen), srclen, dst, dstlen); + + if (!dst) /* return required string length */ + { + INT len; + + for (len = 0; srclen; src++, srclen--) + { + WCHAR wch = *src; + /* tests show that win2k just ignores NORM_IGNORENONSPACE, + * and skips white space and punctuation characters for + * NORM_IGNORESYMBOLS. + */ + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + len++; + } + return len; + } + + if (flags & LCMAP_UPPERCASE) + { + for (dst_ptr = dst; srclen && dstlen; src++, srclen--) + { + WCHAR wch = *src; + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + *dst_ptr++ = toupperW(wch); + dstlen--; + } + } + else if (flags & LCMAP_LOWERCASE) + { + for (dst_ptr = dst; srclen && dstlen; src++, srclen--) + { + WCHAR wch = *src; + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + *dst_ptr++ = tolowerW(wch); + dstlen--; + } + } + else + { + if (src == dst) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + for (dst_ptr = dst; srclen && dstlen; src++, srclen--) + { + WCHAR wch = *src; + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + *dst_ptr++ = wch; + dstlen--; + } + } + + if (srclen) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + return dst_ptr - dst; +} + +/************************************************************************* + * LCMapStringA (KERNEL32.@) + * + * Map characters in a locale sensitive string. + * + * PARAMS + * lcid [I] LCID for the conversion. + * flags [I] Flags controlling the mapping (LCMAP_ constants from "winnls.h"). + * src [I] String to map + * srclen [I] Length of src in chars, or -1 if src is NUL terminated + * dst [O] Destination for mapped string + * dstlen [I] Length of dst in characters + * + * RETURNS + * Success: The length of the mapped string in dst, including the NUL terminator. + * Failure: 0. Use GetLastError() to determine the cause. + */ +INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, + LPSTR dst, INT dstlen) +{ + WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer; + LPWSTR srcW, dstW; + INT ret = 0, srclenW, dstlenW; + UINT locale_cp = CP_ACP; + + if (!src || !srclen || dstlen < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid ); + + srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260); + if (srclenW) + srcW = bufW; + else + { + srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, NULL, 0); + srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR)); + if (!srcW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + MultiByteToWideChar(locale_cp, 0, src, srclen, srcW, srclenW); + } + + if (flags & LCMAP_SORTKEY) + { + if (src == dst) + { + SetLastError(ERROR_INVALID_FLAGS); + goto map_string_exit; + } + ret = wine_get_sortkey(flags, srcW, srclenW, dst, dstlen); + if (ret == 0) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + else + ret++; + goto map_string_exit; + } + + if (flags & SORT_STRINGSORT) + { + SetLastError(ERROR_INVALID_FLAGS); + goto map_string_exit; + } + + dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0); + if (!dstlenW) + goto map_string_exit; + + dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR)); + if (!dstW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto map_string_exit; + } + + LCMapStringW(lcid, flags, srcW, srclenW, dstW, dstlenW); + ret = WideCharToMultiByte(locale_cp, 0, dstW, dstlenW, dst, dstlen, NULL, NULL); + HeapFree(GetProcessHeap(), 0, dstW); + +map_string_exit: + if (srcW != bufW) HeapFree(GetProcessHeap(), 0, srcW); + return ret; +} + +/************************************************************************* + * FoldStringA (KERNEL32.@) + * + * Map characters in a string. + * + * PARAMS + * dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h") + * src [I] String to map + * srclen [I] Length of src, or -1 if src is NUL terminated + * dst [O] Destination for mapped string + * dstlen [I] Length of dst, or 0 to find the required length for the mapped string + * + * RETURNS + * Success: The length of the string written to dst, including the terminating NUL. If + * dstlen is 0, the value returned is the same, but nothing is written to dst, + * and dst may be NULL. + * Failure: 0. Use GetLastError() to determine the cause. + */ +INT WINAPI FoldStringA(DWORD dwFlags, LPCSTR src, INT srclen, + LPSTR dst, INT dstlen) +{ + INT ret = 0, srclenW = 0; + WCHAR *srcW = NULL, *dstW = NULL; + + if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + srclenW = MultiByteToWideChar(CP_ACP, dwFlags & MAP_COMPOSITE ? MB_COMPOSITE : 0, + src, srclen, NULL, 0); + srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR)); + + if (!srcW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto FoldStringA_exit; + } + + MultiByteToWideChar(CP_ACP, dwFlags & MAP_COMPOSITE ? MB_COMPOSITE : 0, + src, srclen, srcW, srclenW); + + dwFlags = (dwFlags & ~MAP_PRECOMPOSED) | MAP_FOLDCZONE; + + ret = FoldStringW(dwFlags, srcW, srclenW, NULL, 0); + if (ret && dstlen) + { + dstW = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR)); + + if (!dstW) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto FoldStringA_exit; + } + + ret = FoldStringW(dwFlags, srcW, srclenW, dstW, ret); + if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL)) + { + ret = 0; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + } + + HeapFree(GetProcessHeap(), 0, dstW); + +FoldStringA_exit: + HeapFree(GetProcessHeap(), 0, srcW); + return ret; +} + +/************************************************************************* + * FoldStringW (KERNEL32.@) + * + * See FoldStringA. + */ +INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, + LPWSTR dst, INT dstlen) +{ + int ret; + + switch (dwFlags & (MAP_COMPOSITE|MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES)) + { + case 0: + if (dwFlags) + break; + /* Fall through for dwFlags == 0 */ + case MAP_PRECOMPOSED|MAP_COMPOSITE: + case MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES: + case MAP_COMPOSITE|MAP_EXPAND_LIGATURES: + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + ret = wine_fold_string(dwFlags, src, srclen, dst, dstlen); + if (!ret) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return ret; +} + +/****************************************************************************** + * CompareStringW (KERNEL32.@) + * + * See CompareStringA. + */ +INT WINAPI CompareStringW(LCID lcid, DWORD style, + LPCWSTR str1, INT len1, LPCWSTR str2, INT len2) +{ + INT ret; + + if (!str1 || !str2) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS| + SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|0x10000000) ) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + /* this style is related to diacritics in Arabic, Japanese, and Hebrew */ + if (style & 0x10000000) + WARN("Ignoring unknown style 0x10000000\n"); + + if (len1 < 0) len1 = strlenW(str1); + if (len2 < 0) len2 = strlenW(str2); + + ret = wine_compare_string(style, str1, len1, str2, len2); + + if (ret) /* need to translate result */ + return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN; + return CSTR_EQUAL; +} + +/****************************************************************************** + * CompareStringA (KERNEL32.@) + * + * Compare two locale sensitive strings. + * + * PARAMS + * lcid [I] LCID for the comparison + * style [I] Flags for the comparison (NORM_ constants from "winnls.h"). + * str1 [I] First string to compare + * len1 [I] Length of str1, or -1 if str1 is NUL terminated + * str2 [I] Second string to compare + * len2 [I] Length of str2, or -1 if str2 is NUL terminated + * + * RETURNS + * Success: CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN depending on whether + * str1 is less than, equal to or greater than str2 respectively. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +INT WINAPI CompareStringA(LCID lcid, DWORD style, + LPCSTR str1, INT len1, LPCSTR str2, INT len2) +{ + WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer; + WCHAR *buf2W = buf1W + 130; + LPWSTR str1W, str2W; + INT len1W, len2W, ret; + UINT locale_cp = CP_ACP; + + if (!str1 || !str2) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (len1 < 0) len1 = strlen(str1); + if (len2 < 0) len2 = strlen(str2); + + if (!(style & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid ); + + len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130); + if (len1W) + str1W = buf1W; + else + { + len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, NULL, 0); + str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR)); + if (!str1W) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W); + } + len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130); + if (len2W) + str2W = buf2W; + else + { + len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, NULL, 0); + str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR)); + if (!str2W) + { + if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + MultiByteToWideChar(locale_cp, 0, str2, len2, str2W, len2W); + } + + ret = CompareStringW(lcid, style, str1W, len1W, str2W, len2W); + + if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W); + if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W); + return ret; +} + +static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName) +{ + UNICODE_STRING keyName; + OBJECT_ATTRIBUTES attr; + HANDLE hkey; + + RtlInitUnicodeString( &keyName, szKeyName ); + InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL); + + if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS) + hkey = 0; + + return hkey; +} + +static BOOL NLS_RegEnumSubKey(HANDLE hKey, UINT ulIndex, LPWSTR szKeyName, + ULONG keyNameSize) +{ + BYTE buffer[80]; + KEY_BASIC_INFORMATION *info = (KEY_BASIC_INFORMATION *)buffer; + DWORD dwLen; + + if (NtEnumerateKey( hKey, ulIndex, KeyBasicInformation, buffer, + sizeof(buffer), &dwLen) != STATUS_SUCCESS || + info->NameLength > keyNameSize) + { + return FALSE; + } + + TRACE("info->Name %s info->NameLength %d\n", debugstr_w(info->Name), info->NameLength); + + memcpy( szKeyName, info->Name, info->NameLength); + szKeyName[info->NameLength / sizeof(WCHAR)] = '\0'; + + TRACE("returning %s\n", debugstr_w(szKeyName)); + return TRUE; +} + +static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex, + LPWSTR szValueName, ULONG valueNameSize, + LPWSTR szValueData, ULONG valueDataSize) +{ + BYTE buffer[80]; + KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer; + DWORD dwLen; + + if (NtEnumerateValueKey( hKey, ulIndex, KeyValueFullInformation, + buffer, sizeof(buffer), &dwLen ) != STATUS_SUCCESS || + info->NameLength > valueNameSize || + info->DataLength > valueDataSize) + { + return FALSE; + } + + TRACE("info->Name %s info->DataLength %d\n", debugstr_w(info->Name), info->DataLength); + + memcpy( szValueName, info->Name, info->NameLength); + szValueName[info->NameLength / sizeof(WCHAR)] = '\0'; + memcpy( szValueData, buffer + info->DataOffset, info->DataLength ); + szValueData[info->DataLength / sizeof(WCHAR)] = '\0'; + + TRACE("returning %s %s\n", debugstr_w(szValueName), debugstr_w(szValueData)); + return TRUE; +} + +static BOOL NLS_RegGetDword(HANDLE hKey, LPCWSTR szValueName, DWORD *lpVal) +{ + BYTE buffer[128]; + const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + DWORD dwSize = sizeof(buffer); + UNICODE_STRING valueName; + + RtlInitUnicodeString( &valueName, szValueName ); + + TRACE("%p, %s\n", hKey, debugstr_w(szValueName)); + if (NtQueryValueKey( hKey, &valueName, KeyValuePartialInformation, + buffer, dwSize, &dwSize ) == STATUS_SUCCESS && + info->DataLength == sizeof(DWORD)) + { + memcpy(lpVal, info->Data, sizeof(DWORD)); + return TRUE; + } + + return FALSE; +} + +static BOOL NLS_GetLanguageGroupName(LGRPID lgrpid, LPWSTR szName, ULONG nameSize) +{ + LANGID langId; + LPCWSTR szResourceName = MAKEINTRESOURCEW(((lgrpid + 0x2000) >> 4) + 1); + HRSRC hResource; + BOOL bRet = FALSE; + + /* FIXME: Is it correct to use the system default langid? */ + langId = GetSystemDefaultLangID(); + + if (SUBLANGID(langId) == SUBLANG_NEUTRAL) + langId = MAKELANGID( PRIMARYLANGID(langId), SUBLANG_DEFAULT ); + + hResource = FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, szResourceName, langId ); + + if (hResource) + { + HGLOBAL hResDir = LoadResource( kernel32_handle, hResource ); + + if (hResDir) + { + ULONG iResourceIndex = lgrpid & 0xf; + LPCWSTR lpResEntry = LockResource( hResDir ); + ULONG i; + + for (i = 0; i < iResourceIndex; i++) + lpResEntry += *lpResEntry + 1; + + if (*lpResEntry < nameSize) + { + memcpy( szName, lpResEntry + 1, *lpResEntry * sizeof(WCHAR) ); + szName[*lpResEntry] = '\0'; + bRet = TRUE; + } + + } + FreeResource( hResource ); + } + return bRet; +} + +/* Registry keys for NLS related information */ + +static const WCHAR szCountryListName[] = { + 'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'T','e','l','e','p','h','o','n','y','\\', + 'C','o','u','n','t','r','y',' ','L','i','s','t','\0' +}; + + +/* Callback function ptrs for EnumSystemLanguageGroupsA/W */ +typedef struct +{ + LANGUAGEGROUP_ENUMPROCA procA; + LANGUAGEGROUP_ENUMPROCW procW; + DWORD dwFlags; + LONG_PTR lParam; +} ENUMLANGUAGEGROUP_CALLBACKS; + +/* Internal implementation of EnumSystemLanguageGroupsA/W */ +static BOOL NLS_EnumSystemLanguageGroups(ENUMLANGUAGEGROUP_CALLBACKS *lpProcs) +{ + WCHAR szNumber[10], szValue[4]; + HANDLE hKey; + BOOL bContinue = TRUE; + ULONG ulIndex = 0; + + if (!lpProcs) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch (lpProcs->dwFlags) + { + case 0: + /* Default to LGRPID_INSTALLED */ + lpProcs->dwFlags = LGRPID_INSTALLED; + /* Fall through... */ + case LGRPID_INSTALLED: + case LGRPID_SUPPORTED: + break; + default: + SetLastError(ERROR_INVALID_FLAGS); + return FALSE; + } + + hKey = NLS_RegOpenKey( 0, szLangGroupsKeyName ); + + if (!hKey) + FIXME("NLS registry key not found. Please apply the default registry file 'wine.inf'\n"); + + while (bContinue) + { + if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber), + szValue, sizeof(szValue) )) + { + BOOL bInstalled = szValue[0] == '1' ? TRUE : FALSE; + LGRPID lgrpid = strtoulW( szNumber, NULL, 16 ); + + TRACE("grpid %s (%sinstalled)\n", debugstr_w(szNumber), + bInstalled ? "" : "not "); + + if (lpProcs->dwFlags == LGRPID_SUPPORTED || bInstalled) + { + WCHAR szGrpName[48]; + + if (!NLS_GetLanguageGroupName( lgrpid, szGrpName, sizeof(szGrpName) / sizeof(WCHAR) )) + szGrpName[0] = '\0'; + + if (lpProcs->procW) + bContinue = lpProcs->procW( lgrpid, szNumber, szGrpName, lpProcs->dwFlags, + lpProcs->lParam ); + else + { + char szNumberA[sizeof(szNumber)/sizeof(WCHAR)]; + char szGrpNameA[48]; + + /* FIXME: MSDN doesn't say which code page the W->A translation uses, + * or whether the language names are ever localised. Assume CP_ACP. + */ + + WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0); + WideCharToMultiByte(CP_ACP, 0, szGrpName, -1, szGrpNameA, sizeof(szGrpNameA), 0, 0); + + bContinue = lpProcs->procA( lgrpid, szNumberA, szGrpNameA, lpProcs->dwFlags, + lpProcs->lParam ); + } + } + + ulIndex++; + } + else + bContinue = FALSE; + + if (!bContinue) + break; + } + + if (hKey) + NtClose( hKey ); + + return TRUE; +} + +/****************************************************************************** + * EnumSystemLanguageGroupsA (KERNEL32.@) + * + * Call a users function for each language group available on the system. + * + * PARAMS + * pLangGrpEnumProc [I] Callback function to call for each language group + * dwFlags [I] LGRPID_SUPPORTED=All Supported, LGRPID_INSTALLED=Installed only + * lParam [I] User parameter to pass to pLangGrpEnumProc + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI EnumSystemLanguageGroupsA(LANGUAGEGROUP_ENUMPROCA pLangGrpEnumProc, + DWORD dwFlags, LONG_PTR lParam) +{ + ENUMLANGUAGEGROUP_CALLBACKS procs; + + TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam); + + procs.procA = pLangGrpEnumProc; + procs.procW = NULL; + procs.dwFlags = dwFlags; + procs.lParam = lParam; + + return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL); +} + +/****************************************************************************** + * EnumSystemLanguageGroupsW (KERNEL32.@) + * + * See EnumSystemLanguageGroupsA. + */ +BOOL WINAPI EnumSystemLanguageGroupsW(LANGUAGEGROUP_ENUMPROCW pLangGrpEnumProc, + DWORD dwFlags, LONG_PTR lParam) +{ + ENUMLANGUAGEGROUP_CALLBACKS procs; + + TRACE("(%p,0x%08X,0x%08lX)\n", pLangGrpEnumProc, dwFlags, lParam); + + procs.procA = NULL; + procs.procW = pLangGrpEnumProc; + procs.dwFlags = dwFlags; + procs.lParam = lParam; + + return NLS_EnumSystemLanguageGroups( pLangGrpEnumProc ? &procs : NULL); +} + +/****************************************************************************** + * IsValidLanguageGroup (KERNEL32.@) + * + * Determine if a language group is supported and/or installed. + * + * PARAMS + * lgrpid [I] Language Group Id (LGRPID_ values from "winnls.h") + * dwFlags [I] LGRPID_SUPPORTED=Supported, LGRPID_INSTALLED=Installed + * + * RETURNS + * TRUE, if lgrpid is supported and/or installed, according to dwFlags. + * FALSE otherwise. + */ +BOOL WINAPI IsValidLanguageGroup(LGRPID lgrpid, DWORD dwFlags) +{ + static const WCHAR szFormat[] = { '%','x','\0' }; + WCHAR szValueName[16], szValue[2]; + BOOL bSupported = FALSE, bInstalled = FALSE; + HANDLE hKey; + + + switch (dwFlags) + { + case LGRPID_INSTALLED: + case LGRPID_SUPPORTED: + + hKey = NLS_RegOpenKey( 0, szLangGroupsKeyName ); + + sprintfW( szValueName, szFormat, lgrpid ); + + if (NLS_RegGetDword( hKey, szValueName, (LPDWORD)szValue )) + { + bSupported = TRUE; + + if (szValue[0] == '1') + bInstalled = TRUE; + } + + if (hKey) + NtClose( hKey ); + + break; + } + + if ((dwFlags == LGRPID_SUPPORTED && bSupported) || + (dwFlags == LGRPID_INSTALLED && bInstalled)) + return TRUE; + + return FALSE; +} + +/* Callback function ptrs for EnumLanguageGrouplocalesA/W */ +typedef struct +{ + LANGGROUPLOCALE_ENUMPROCA procA; + LANGGROUPLOCALE_ENUMPROCW procW; + DWORD dwFlags; + LGRPID lgrpid; + LONG_PTR lParam; +} ENUMLANGUAGEGROUPLOCALE_CALLBACKS; + +/* Internal implementation of EnumLanguageGrouplocalesA/W */ +static BOOL NLS_EnumLanguageGroupLocales(ENUMLANGUAGEGROUPLOCALE_CALLBACKS *lpProcs) +{ + static const WCHAR szAlternateSortsKeyName[] = { + 'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s','\0' + }; + WCHAR szNumber[10], szValue[4]; + HANDLE hKey; + BOOL bContinue = TRUE, bAlternate = FALSE; + LGRPID lgrpid; + ULONG ulIndex = 1; /* Ignore default entry of 1st key */ + + if (!lpProcs || !lpProcs->lgrpid || lpProcs->lgrpid > LGRPID_ARMENIAN) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (lpProcs->dwFlags) + { + SetLastError(ERROR_INVALID_FLAGS); + return FALSE; + } + + hKey = NLS_RegOpenKey( 0, szLocaleKeyName ); + + if (!hKey) + WARN("NLS registry key not found. Please apply the default registry file 'wine.inf'\n"); + + while (bContinue) + { + if (NLS_RegEnumValue( hKey, ulIndex, szNumber, sizeof(szNumber), + szValue, sizeof(szValue) )) + { + lgrpid = strtoulW( szValue, NULL, 16 ); + + TRACE("lcid %s, grpid %d (%smatched)\n", debugstr_w(szNumber), + lgrpid, lgrpid == lpProcs->lgrpid ? "" : "not "); + + if (lgrpid == lpProcs->lgrpid) + { + LCID lcid; + + lcid = strtoulW( szNumber, NULL, 16 ); + + /* FIXME: native returns extra text for a few (17/150) locales, e.g: + * '00000437 ;Georgian' + * At present we only pass the LCID string. + */ + + if (lpProcs->procW) + bContinue = lpProcs->procW( lgrpid, lcid, szNumber, lpProcs->lParam ); + else + { + char szNumberA[sizeof(szNumber)/sizeof(WCHAR)]; + + WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0); + + bContinue = lpProcs->procA( lgrpid, lcid, szNumberA, lpProcs->lParam ); + } + } + + ulIndex++; + } + else + { + /* Finished enumerating this key */ + if (!bAlternate) + { + /* Enumerate alternate sorts also */ + hKey = NLS_RegOpenKey( hKey, szAlternateSortsKeyName ); + bAlternate = TRUE; + ulIndex = 0; + } + else + bContinue = FALSE; /* Finished both keys */ + } + + if (!bContinue) + break; + } + + if (hKey) + NtClose( hKey ); + + return TRUE; +} + +/****************************************************************************** + * EnumLanguageGroupLocalesA (KERNEL32.@) + * + * Call a users function for every locale in a language group available on the system. + * + * PARAMS + * pLangGrpLcEnumProc [I] Callback function to call for each locale + * lgrpid [I] Language group (LGRPID_ values from "winnls.h") + * dwFlags [I] Reserved, set to 0 + * lParam [I] User parameter to pass to pLangGrpLcEnumProc + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI EnumLanguageGroupLocalesA(LANGGROUPLOCALE_ENUMPROCA pLangGrpLcEnumProc, + LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam) +{ + ENUMLANGUAGEGROUPLOCALE_CALLBACKS callbacks; + + TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam); + + callbacks.procA = pLangGrpLcEnumProc; + callbacks.procW = NULL; + callbacks.dwFlags = dwFlags; + callbacks.lgrpid = lgrpid; + callbacks.lParam = lParam; + + return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL ); +} + +/****************************************************************************** + * EnumLanguageGroupLocalesW (KERNEL32.@) + * + * See EnumLanguageGroupLocalesA. + */ +BOOL WINAPI EnumLanguageGroupLocalesW(LANGGROUPLOCALE_ENUMPROCW pLangGrpLcEnumProc, + LGRPID lgrpid, DWORD dwFlags, LONG_PTR lParam) +{ + ENUMLANGUAGEGROUPLOCALE_CALLBACKS callbacks; + + TRACE("(%p,0x%08X,0x%08X,0x%08lX)\n", pLangGrpLcEnumProc, lgrpid, dwFlags, lParam); + + callbacks.procA = NULL; + callbacks.procW = pLangGrpLcEnumProc; + callbacks.dwFlags = dwFlags; + callbacks.lgrpid = lgrpid; + callbacks.lParam = lParam; + + return NLS_EnumLanguageGroupLocales( pLangGrpLcEnumProc ? &callbacks : NULL ); +} + +/* Callback function ptrs for EnumSystemCodePagesA/W */ +typedef struct +{ + CODEPAGE_ENUMPROCA procA; + CODEPAGE_ENUMPROCW procW; + DWORD dwFlags; +} ENUMSYSTEMCODEPAGES_CALLBACKS; + +/* Internal implementation of EnumSystemCodePagesA/W */ +static BOOL NLS_EnumSystemCodePages(ENUMSYSTEMCODEPAGES_CALLBACKS *lpProcs) +{ + WCHAR szNumber[5 + 1], szValue[MAX_PATH]; + HANDLE hKey; + BOOL bContinue = TRUE; + ULONG ulIndex = 0; + + if (!lpProcs) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch (lpProcs->dwFlags) + { + case CP_INSTALLED: + case CP_SUPPORTED: + break; + default: + SetLastError(ERROR_INVALID_FLAGS); + return FALSE; + } + + hKey = NLS_RegOpenKey(0, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage"); + if (!hKey) + { + WARN("NLS_RegOpenKey() failed\n"); + return FALSE; + } + + while (bContinue) + { + if (NLS_RegEnumValue(hKey, ulIndex, szNumber, sizeof(szNumber), + szValue, sizeof(szValue))) + { + if ((lpProcs->dwFlags == CP_SUPPORTED)|| + ((lpProcs->dwFlags == CP_INSTALLED)&&(wcslen(szValue) > 2))) + { + if (lpProcs->procW) + { + bContinue = lpProcs->procW(szNumber); + } + else + { + char szNumberA[sizeof(szNumber)/sizeof(WCHAR)]; + + WideCharToMultiByte(CP_ACP, 0, szNumber, -1, szNumberA, sizeof(szNumberA), 0, 0); + bContinue = lpProcs->procA(szNumberA); + } + } + + ulIndex++; + + } else bContinue = FALSE; + + if (!bContinue) + break; + } + + if (hKey) + NtClose(hKey); + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +EnumSystemCodePagesW ( + CODEPAGE_ENUMPROCW lpCodePageEnumProc, + DWORD dwFlags + ) +{ + ENUMSYSTEMCODEPAGES_CALLBACKS procs; + + TRACE("(%p,0x%08X,0x%08lX)\n", lpCodePageEnumProc, dwFlags); + + procs.procA = NULL; + procs.procW = lpCodePageEnumProc; + procs.dwFlags = dwFlags; + + return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL); +} + + +/* + * @implemented + */ +BOOL +WINAPI +EnumSystemCodePagesA ( + CODEPAGE_ENUMPROCA lpCodePageEnumProc, + DWORD dwFlags + ) +{ + ENUMSYSTEMCODEPAGES_CALLBACKS procs; + + TRACE("(%p,0x%08X,0x%08lX)\n", lpCodePageEnumProc, dwFlags); + + procs.procA = lpCodePageEnumProc; + procs.procW = NULL; + procs.dwFlags = dwFlags; + + return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL); +} +/****************************************************************************** + * EnumSystemGeoID (KERNEL32.@) + * + * Call a users function for every location available on the system. + * + * PARAMS + * geoclass [I] Type of information desired (SYSGEOTYPE enum from "winnls.h") + * reserved [I] Reserved, set to 0 + * pGeoEnumProc [I] Callback function to call for each location + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. Use GetLastError() to determine the cause. + */ +BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID reserved, GEO_ENUMPROC pGeoEnumProc) +{ + static const WCHAR szCountryCodeValueName[] = { + 'C','o','u','n','t','r','y','C','o','d','e','\0' + }; + WCHAR szNumber[10]; + HANDLE hKey; + ULONG ulIndex = 0; + + TRACE("(0x%08X,0x%08X,%p)\n", geoclass, reserved, pGeoEnumProc); + + if (geoclass != GEOCLASS_NATION || reserved || !pGeoEnumProc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + hKey = NLS_RegOpenKey( 0, szCountryListName ); + + while (NLS_RegEnumSubKey( hKey, ulIndex, szNumber, sizeof(szNumber) )) + { + BOOL bContinue = TRUE; + DWORD dwGeoId; + HANDLE hSubKey = NLS_RegOpenKey( hKey, szNumber ); + + if (hSubKey) + { + if (NLS_RegGetDword( hSubKey, szCountryCodeValueName, &dwGeoId )) + { + TRACE("Got geoid %d\n", dwGeoId); + + if (!pGeoEnumProc( dwGeoId )) + bContinue = FALSE; + } + + NtClose( hSubKey ); + } + + if (!bContinue) + break; + + ulIndex++; + } + + if (hKey) + NtClose( hKey ); + + return TRUE; +} + +/****************************************************************************** + * InvalidateNLSCache (KERNEL32.@) + * + * Invalidate the cache of NLS values. + * + * PARAMS + * None. + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. + */ +BOOL WINAPI InvalidateNLSCache(void) +{ + FIXME("() stub\n"); + return FALSE; +} + +/****************************************************************************** + * GetUserGeoID (KERNEL32.@) + */ +GEOID WINAPI GetUserGeoID( GEOCLASS GeoClass ) +{ + GEOID ret = GEOID_NOT_AVAILABLE; + static const WCHAR geoW[] = {'G','e','o',0}; + static const WCHAR nationW[] = {'N','a','t','i','o','n',0}; + WCHAR bufferW[40], *end; + DWORD count; + HANDLE hkey, hSubkey = 0; + UNICODE_STRING keyW; + const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)bufferW; + RtlInitUnicodeString( &keyW, nationW ); + count = sizeof(bufferW); + + if(!(hkey = create_registry_key())) return ret; + + switch( GeoClass ){ + case GEOCLASS_NATION: + if ((hSubkey = NLS_RegOpenKey(hkey, geoW))) + { + if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation, + bufferW, count, &count) == STATUS_SUCCESS ) && info->DataLength) + ret = strtolW((LPCWSTR)info->Data, &end, 10); + } + break; + case GEOCLASS_REGION: + FIXME("GEOCLASS_REGION not handled yet\n"); + break; + } + + NtClose(hkey); + if (hSubkey) NtClose(hSubkey); + return ret; +} + +/****************************************************************************** + * SetUserGeoID (KERNEL32.@) + */ +BOOL WINAPI SetUserGeoID( GEOID GeoID ) +{ + static const WCHAR geoW[] = {'G','e','o',0}; + static const WCHAR nationW[] = {'N','a','t','i','o','n',0}; + static const WCHAR formatW[] = {'%','i',0}; + UNICODE_STRING nameW,keyW; + WCHAR bufferW[10]; + OBJECT_ATTRIBUTES attr; + HANDLE hkey; + + if(!(hkey = create_registry_key())) return FALSE; + + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, geoW ); + RtlInitUnicodeString( &keyW, nationW ); + + if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS) + + { + NtClose(attr.RootDirectory); + return FALSE; + } + + sprintfW(bufferW, formatW, GeoID); + NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR)); + NtClose(attr.RootDirectory); + NtClose(hkey); + return TRUE; +} + +typedef struct +{ + union + { + UILANGUAGE_ENUMPROCA procA; + UILANGUAGE_ENUMPROCW procW; + } u; + DWORD flags; + LONG_PTR param; +} ENUM_UILANG_CALLBACK; + +static BOOL CALLBACK enum_uilang_proc_a( HMODULE hModule, LPCSTR type, + LPCSTR name, WORD LangID, LONG_PTR lParam ) +{ + ENUM_UILANG_CALLBACK *enum_uilang = (ENUM_UILANG_CALLBACK *)lParam; + char buf[20]; + + sprintf(buf, "%08x", (UINT)LangID); + return enum_uilang->u.procA( buf, enum_uilang->param ); +} + +static BOOL CALLBACK enum_uilang_proc_w( HMODULE hModule, LPCWSTR type, + LPCWSTR name, WORD LangID, LONG_PTR lParam ) +{ + static const WCHAR formatW[] = {'%','0','8','x',0}; + ENUM_UILANG_CALLBACK *enum_uilang = (ENUM_UILANG_CALLBACK *)lParam; + WCHAR buf[20]; + + sprintfW( buf, formatW, (UINT)LangID ); + return enum_uilang->u.procW( buf, enum_uilang->param ); +} + +/****************************************************************************** + * EnumUILanguagesA (KERNEL32.@) + */ +BOOL WINAPI EnumUILanguagesA(UILANGUAGE_ENUMPROCA pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam) +{ + ENUM_UILANG_CALLBACK enum_uilang; + + TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam); + + if(!pUILangEnumProc) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if(dwFlags) { + SetLastError(ERROR_INVALID_FLAGS); + return FALSE; + } + + enum_uilang.u.procA = pUILangEnumProc; + enum_uilang.flags = dwFlags; + enum_uilang.param = lParam; + + EnumResourceLanguagesA( kernel32_handle, (LPCSTR)RT_STRING, + (LPCSTR)LOCALE_ILANGUAGE, enum_uilang_proc_a, + (LONG_PTR)&enum_uilang); + return TRUE; +} + +/****************************************************************************** + * EnumUILanguagesW (KERNEL32.@) + */ +BOOL WINAPI EnumUILanguagesW(UILANGUAGE_ENUMPROCW pUILangEnumProc, DWORD dwFlags, LONG_PTR lParam) +{ + ENUM_UILANG_CALLBACK enum_uilang; + + TRACE("%p, %x, %lx\n", pUILangEnumProc, dwFlags, lParam); + + + if(!pUILangEnumProc) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if(dwFlags) { + SetLastError(ERROR_INVALID_FLAGS); + return FALSE; + } + + enum_uilang.u.procW = pUILangEnumProc; + enum_uilang.flags = dwFlags; + enum_uilang.param = lParam; + + EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING, + (LPCWSTR)LOCALE_ILANGUAGE, enum_uilang_proc_w, + (LONG_PTR)&enum_uilang); + return TRUE; +} + +INT WINAPI GetGeoInfoW(GEOID GeoId, GEOTYPE GeoType, LPWSTR lpGeoData, + int cchData, LANGID language) +{ + FIXME("%d %d %p %d %d\n", GeoId, GeoType, lpGeoData, cchData, language); + return 0; +} + +INT WINAPI GetGeoInfoA(GEOID GeoId, GEOTYPE GeoType, LPSTR lpGeoData, + int cchData, LANGID language) +{ + FIXME("%d %d %p %d %d\n", GeoId, GeoType, lpGeoData, cchData, language); + return 0; +} diff --git a/dll/win32/kernel32/winnls/string/lcformat.c b/dll/win32/kernel32/winnls/string/lcformat.c new file mode 100644 index 00000000000..bf8b7ae93c4 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/lcformat.c @@ -0,0 +1,2302 @@ +/* + * Locale-dependent format handling + * + * Copyright 1995 Martin von Loewis + * Copyright 1998 David Lee Lambert + * Copyright 2000 Julio César G√°zquez + * Copyright 2003 Jon Griffiths + * Copyright 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//#include "config.h" +//#include "wine/port.h" + +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wine/unicode.h" +#include "wine/debug.h" +#include "winternl.h" + +#define CRITICAL_SECTION RTL_CRITICAL_SECTION +#define CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG +#define CALINFO_MAX_YEAR 2029 + +#define HeapAlloc RtlAllocateHeap +#define HeapReAlloc RtlReAllocateHeap +#define HeapFree RtlFreeHeap + +WINE_DEFAULT_DEBUG_CHANNEL(nls); + +#define DATE_DATEVARSONLY 0x0100 /* only date stuff: yMdg */ +#define TIME_TIMEVARSONLY 0x0200 /* only time stuff: hHmst */ + +/* Since calculating the formatting data for each locale is time-consuming, + * we get the format data for each locale only once and cache it in memory. + * We cache both the system default and user overridden data, after converting + * them into the formats that the functions here expect. Since these functions + * will typically be called with only a small number of the total locales + * installed, the memory overhead is minimal while the speedup is significant. + * + * Our cache takes the form of a singly linked list, whose node is below: + */ +#define NLS_NUM_CACHED_STRINGS 57 + +typedef struct _NLS_FORMAT_NODE +{ + LCID lcid; /* Locale Id */ + DWORD dwFlags; /* 0 or LOCALE_NOUSEROVERRIDE */ + DWORD dwCodePage; /* Default code page (if LOCALE_USE_ANSI_CP not given) */ + NUMBERFMTW fmt; /* Default format for numbers */ + CURRENCYFMTW cyfmt; /* Default format for currencies */ + LPWSTR lppszStrings[NLS_NUM_CACHED_STRINGS]; /* Default formats,day/month names */ + WCHAR szShortAM[2]; /* Short 'AM' marker */ + WCHAR szShortPM[2]; /* Short 'PM' marker */ + struct _NLS_FORMAT_NODE *next; +} NLS_FORMAT_NODE; + +/* Macros to get particular data strings from a format node */ +#define GetNegative(fmt) fmt->lppszStrings[0] +#define GetLongDate(fmt) fmt->lppszStrings[1] +#define GetShortDate(fmt) fmt->lppszStrings[2] +#define GetTime(fmt) fmt->lppszStrings[3] +#define GetAM(fmt) fmt->lppszStrings[54] +#define GetPM(fmt) fmt->lppszStrings[55] +#define GetYearMonth(fmt) fmt->lppszStrings[56] + +#define GetLongDay(fmt,day) fmt->lppszStrings[4 + day] +#define GetShortDay(fmt,day) fmt->lppszStrings[11 + day] +#define GetLongMonth(fmt,mth) fmt->lppszStrings[18 + mth] +#define GetGenitiveMonth(fmt,mth) fmt->lppszStrings[30 + mth] +#define GetShortMonth(fmt,mth) fmt->lppszStrings[42 + mth] + +/* Write access to the cache is protected by this critical section */ +static CRITICAL_SECTION NLS_FormatsCS; +static CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = +{ + 0, 0, &NLS_FormatsCS, + { &NLS_FormatsCS_debug.ProcessLocksList, + &NLS_FormatsCS_debug.ProcessLocksList }, + 0, 0, 0 +}; +static CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; + +/************************************************************************** + * NLS_GetLocaleNumber + * + * Get a numeric locale format value. + */ +static DWORD NLS_GetLocaleNumber(LCID lcid, DWORD dwFlags) +{ + WCHAR szBuff[80]; + DWORD dwVal = 0; + + szBuff[0] = '\0'; + GetLocaleInfoW(lcid, dwFlags, szBuff, sizeof(szBuff) / sizeof(WCHAR)); + + if (szBuff[0] && szBuff[1] == ';' && szBuff[2] != '0') + dwVal = (szBuff[0] - '0') * 10 + (szBuff[2] - '0'); + else + { + const WCHAR* iter = szBuff; + dwVal = 0; + while(*iter >= '0' && *iter <= '9') + dwVal = dwVal * 10 + (*iter++ - '0'); + } + return dwVal; +} + +/************************************************************************** + * NLS_GetLocaleString + * + * Get a string locale format value. + */ +static WCHAR* NLS_GetLocaleString(LCID lcid, DWORD dwFlags) +{ + WCHAR szBuff[80], *str; + DWORD dwLen; + + szBuff[0] = '\0'; + GetLocaleInfoW(lcid, dwFlags, szBuff, sizeof(szBuff) / sizeof(WCHAR)); + dwLen = strlenW(szBuff) + 1; + str = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR)); + if (str) + memcpy(str, szBuff, dwLen * sizeof(WCHAR)); + return str; +} + +#define GET_LOCALE_NUMBER(num, type) num = NLS_GetLocaleNumber(lcid, type|dwFlags); \ + TRACE( #type ": %d (%08x)\n", (DWORD)num, (DWORD)num) + +#define GET_LOCALE_STRING(str, type) str = NLS_GetLocaleString(lcid, type|dwFlags); \ + TRACE( #type ": %s\n", debugstr_w(str)) + +/************************************************************************** + * NLS_GetFormats + * + * Calculate (and cache) the number formats for a locale. + */ +static const NLS_FORMAT_NODE *NLS_GetFormats(LCID lcid, DWORD dwFlags) +{ + /* GetLocaleInfo() identifiers for cached formatting strings */ + static const LCTYPE NLS_LocaleIndices[] = { + LOCALE_SNEGATIVESIGN, + LOCALE_SLONGDATE, LOCALE_SSHORTDATE, + LOCALE_STIMEFORMAT, + LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, + LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7, + LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, + LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6, + LOCALE_SABBREVDAYNAME7, + LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, + LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, + LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9, + LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12, + LOCALE_SMONTHNAME1 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME2 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME3 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME4 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME5 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME6 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME7 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME8 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME9 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME10 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME11 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SMONTHNAME12 | LOCALE_RETURN_GENITIVE_NAMES, + LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3, + LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6, + LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9, + LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12, + LOCALE_S1159, LOCALE_S2359, + LOCALE_SYEARMONTH + }; + static NLS_FORMAT_NODE *NLS_CachedFormats = NULL; + NLS_FORMAT_NODE *node = NLS_CachedFormats; + + dwFlags &= LOCALE_NOUSEROVERRIDE; + + TRACE("(0x%04x,0x%08x)\n", lcid, dwFlags); + + /* See if we have already cached the locales number format */ + while (node && (node->lcid != lcid || node->dwFlags != dwFlags) && node->next) + node = node->next; + + if (!node || node->lcid != lcid || node->dwFlags != dwFlags) + { + NLS_FORMAT_NODE *new_node; + DWORD i; + + TRACE("Creating new cache entry\n"); + + if (!(new_node = HeapAlloc(GetProcessHeap(), 0, sizeof(NLS_FORMAT_NODE)))) + return NULL; + + GET_LOCALE_NUMBER(new_node->dwCodePage, LOCALE_IDEFAULTANSICODEPAGE); + + /* Number Format */ + new_node->lcid = lcid; + new_node->dwFlags = dwFlags; + new_node->next = NULL; + + GET_LOCALE_NUMBER(new_node->fmt.NumDigits, LOCALE_IDIGITS); + GET_LOCALE_NUMBER(new_node->fmt.LeadingZero, LOCALE_ILZERO); + GET_LOCALE_NUMBER(new_node->fmt.NegativeOrder, LOCALE_INEGNUMBER); + + GET_LOCALE_NUMBER(new_node->fmt.Grouping, LOCALE_SGROUPING); + if (new_node->fmt.Grouping > 9 && new_node->fmt.Grouping != 32) + { + WARN("LOCALE_SGROUPING (%d) unhandled, please report!\n", + new_node->fmt.Grouping); + new_node->fmt.Grouping = 0; + } + + GET_LOCALE_STRING(new_node->fmt.lpDecimalSep, LOCALE_SDECIMAL); + GET_LOCALE_STRING(new_node->fmt.lpThousandSep, LOCALE_STHOUSAND); + + /* Currency Format */ + new_node->cyfmt.NumDigits = new_node->fmt.NumDigits; + new_node->cyfmt.LeadingZero = new_node->fmt.LeadingZero; + + GET_LOCALE_NUMBER(new_node->cyfmt.Grouping, LOCALE_SGROUPING); + + if (new_node->cyfmt.Grouping > 9) + { + WARN("LOCALE_SMONGROUPING (%d) unhandled, please report!\n", + new_node->cyfmt.Grouping); + new_node->cyfmt.Grouping = 0; + } + + GET_LOCALE_NUMBER(new_node->cyfmt.NegativeOrder, LOCALE_INEGCURR); + if (new_node->cyfmt.NegativeOrder > 15) + { + WARN("LOCALE_INEGCURR (%d) unhandled, please report!\n", + new_node->cyfmt.NegativeOrder); + new_node->cyfmt.NegativeOrder = 0; + } + GET_LOCALE_NUMBER(new_node->cyfmt.PositiveOrder, LOCALE_ICURRENCY); + if (new_node->cyfmt.PositiveOrder > 3) + { + WARN("LOCALE_IPOSCURR (%d) unhandled,please report!\n", + new_node->cyfmt.PositiveOrder); + new_node->cyfmt.PositiveOrder = 0; + } + GET_LOCALE_STRING(new_node->cyfmt.lpDecimalSep, LOCALE_SMONDECIMALSEP); + GET_LOCALE_STRING(new_node->cyfmt.lpThousandSep, LOCALE_SMONTHOUSANDSEP); + GET_LOCALE_STRING(new_node->cyfmt.lpCurrencySymbol, LOCALE_SCURRENCY); + + /* Date/Time Format info, negative character, etc */ + for (i = 0; i < sizeof(NLS_LocaleIndices)/sizeof(NLS_LocaleIndices[0]); i++) + { + GET_LOCALE_STRING(new_node->lppszStrings[i], NLS_LocaleIndices[i]); + } + /* Save some memory if month genitive name is the same or not present */ + for (i = 0; i < 12; i++) + { + if (strcmpW(GetLongMonth(new_node, i), GetGenitiveMonth(new_node, i)) == 0) + { + HeapFree(GetProcessHeap(), 0, GetGenitiveMonth(new_node, i)); + GetGenitiveMonth(new_node, i) = NULL; + } + } + + new_node->szShortAM[0] = GetAM(new_node)[0]; new_node->szShortAM[1] = '\0'; + new_node->szShortPM[0] = GetPM(new_node)[0]; new_node->szShortPM[1] = '\0'; + + /* Now add the computed format to the cache */ + RtlEnterCriticalSection(&NLS_FormatsCS); + + /* Search again: We may have raced to add the node */ + node = NLS_CachedFormats; + while (node && (node->lcid != lcid || node->dwFlags != dwFlags) && node->next) + node = node->next; + + if (!node) + { + node = NLS_CachedFormats = new_node; /* Empty list */ + new_node = NULL; + } + else if (node->lcid != lcid || node->dwFlags != dwFlags) + { + node->next = new_node; /* Not in the list, add to end */ + node = new_node; + new_node = NULL; + } + + RtlLeaveCriticalSection(&NLS_FormatsCS); + + if (new_node) + { + /* We raced and lost: The node was already added by another thread. + * node points to the currently cached node, so free new_node. + */ + for (i = 0; i < sizeof(NLS_LocaleIndices)/sizeof(NLS_LocaleIndices[0]); i++) + HeapFree(GetProcessHeap(), 0, new_node->lppszStrings[i]); + HeapFree(GetProcessHeap(), 0, new_node->fmt.lpDecimalSep); + HeapFree(GetProcessHeap(), 0, new_node->fmt.lpThousandSep); + HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpDecimalSep); + HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpThousandSep); + HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpCurrencySymbol); + HeapFree(GetProcessHeap(), 0, new_node); + } + } + return node; +} + +/************************************************************************** + * NLS_IsUnicodeOnlyLcid + * + * Determine if a locale is Unicode only, and thus invalid in ASCII calls. + */ +BOOL NLS_IsUnicodeOnlyLcid(LCID lcid) +{ + lcid = ConvertDefaultLocale(lcid); + + switch (PRIMARYLANGID(lcid)) + { + case LANG_ARMENIAN: + case LANG_DIVEHI: + case LANG_GEORGIAN: + case LANG_GUJARATI: + case LANG_HINDI: + case LANG_KANNADA: + case LANG_KONKANI: + case LANG_MARATHI: + case LANG_PUNJABI: + case LANG_SANSKRIT: + TRACE("lcid 0x%08x: langid 0x%4x is Unicode Only\n", lcid, PRIMARYLANGID(lcid)); + return TRUE; + default: + return FALSE; + } +} + +/* + * Formatting of dates, times, numbers and currencies. + */ + +#define IsLiteralMarker(p) (p == '\'') +#define IsDateFmtChar(p) (p == 'd'||p == 'M'||p == 'y'||p == 'g') +#define IsTimeFmtChar(p) (p == 'H'||p == 'h'||p == 'm'||p == 's'||p == 't') + +/* Only the following flags can be given if a date/time format is specified */ +#define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY) +#define TIME_FORMAT_FLAGS (TIME_TIMEVARSONLY|TIME_FORCE24HOURFORMAT| \ + TIME_NOMINUTESORSECONDS|TIME_NOSECONDS| \ + TIME_NOTIMEMARKER) + +/****************************************************************************** + * NLS_GetDateTimeFormatW + * + * Performs the formatting for GetDateFormatW/GetTimeFormatW. + * + * FIXME + * DATE_USE_ALT_CALENDAR - Requires GetCalendarInfo to work first. + * DATE_LTRREADING/DATE_RTLREADING - Not yet implemented. + */ +static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags, + const SYSTEMTIME* lpTime, LPCWSTR lpFormat, + LPWSTR lpStr, INT cchOut) +{ + const NLS_FORMAT_NODE *node; + SYSTEMTIME st; + INT cchWritten = 0; + INT lastFormatPos = 0; + BOOL bSkipping = FALSE; /* Skipping text around marker? */ + BOOL d_dd_formatted = FALSE; /* previous formatted part was for d or dd */ + + /* Verify our arguments */ + if ((cchOut && !lpStr) || !(node = NLS_GetFormats(lcid, dwFlags))) + goto invalid_parameter; + + if (dwFlags & ~(DATE_DATEVARSONLY|TIME_TIMEVARSONLY)) + { + if (lpFormat && + ((dwFlags & DATE_DATEVARSONLY && dwFlags & ~DATE_FORMAT_FLAGS) || + (dwFlags & TIME_TIMEVARSONLY && dwFlags & ~TIME_FORMAT_FLAGS))) + { + goto invalid_flags; + } + + if (dwFlags & DATE_DATEVARSONLY) + { + if ((dwFlags & (DATE_LTRREADING|DATE_RTLREADING)) == (DATE_LTRREADING|DATE_RTLREADING)) + goto invalid_flags; + else if (dwFlags & (DATE_LTRREADING|DATE_RTLREADING)) + FIXME("Unsupported flags: DATE_LTRREADING/DATE_RTLREADING\n"); + + switch (dwFlags & (DATE_SHORTDATE|DATE_LONGDATE|DATE_YEARMONTH)) + { + case 0: + break; + case DATE_SHORTDATE: + case DATE_LONGDATE: + case DATE_YEARMONTH: + if (lpFormat) + goto invalid_flags; + break; + default: + goto invalid_flags; + } + } + } + + if (!lpFormat) + { + /* Use the appropriate default format */ + if (dwFlags & DATE_DATEVARSONLY) + { + if (dwFlags & DATE_YEARMONTH) + lpFormat = GetYearMonth(node); + else if (dwFlags & DATE_LONGDATE) + lpFormat = GetLongDate(node); + else + lpFormat = GetShortDate(node); + } + else + lpFormat = GetTime(node); + } + + if (!lpTime) + { + GetLocalTime(&st); /* Default to current time */ + lpTime = &st; + } + else + { + if (dwFlags & DATE_DATEVARSONLY) + { + FILETIME ftTmp; + + /* Verify the date and correct the D.O.W. if needed */ + memset(&st, 0, sizeof(st)); + st.wYear = lpTime->wYear; + st.wMonth = lpTime->wMonth; + st.wDay = lpTime->wDay; + + if (st.wDay > 31 || st.wMonth > 12 || !SystemTimeToFileTime(&st, &ftTmp)) + goto invalid_parameter; + + FileTimeToSystemTime(&ftTmp, &st); + lpTime = &st; + } + + if (dwFlags & TIME_TIMEVARSONLY) + { + /* Verify the time */ + if (lpTime->wHour > 24 || lpTime->wMinute > 59 || lpTime->wSecond > 59) + goto invalid_parameter; + } + } + + /* Format the output */ + while (*lpFormat) + { + if (IsLiteralMarker(*lpFormat)) + { + /* Start of a literal string */ + lpFormat++; + + /* Loop until the end of the literal marker or end of the string */ + while (*lpFormat) + { + if (IsLiteralMarker(*lpFormat)) + { + lpFormat++; + if (!IsLiteralMarker(*lpFormat)) + break; /* Terminating literal marker */ + } + + if (!cchOut) + cchWritten++; /* Count size only */ + else if (cchWritten >= cchOut) + goto overrun; + else if (!bSkipping) + { + lpStr[cchWritten] = *lpFormat; + cchWritten++; + } + lpFormat++; + } + } + else if ((dwFlags & DATE_DATEVARSONLY && IsDateFmtChar(*lpFormat)) || + (dwFlags & TIME_TIMEVARSONLY && IsTimeFmtChar(*lpFormat))) + { + WCHAR buff[32], fmtChar; + LPCWSTR szAdd = NULL; + DWORD dwVal = 0; + int count = 0, dwLen; + + bSkipping = FALSE; + + fmtChar = *lpFormat; + while (*lpFormat == fmtChar) + { + count++; + lpFormat++; + } + buff[0] = '\0'; + + if (fmtChar != 'M') d_dd_formatted = FALSE; + switch(fmtChar) + { + case 'd': + if (count >= 4) + szAdd = GetLongDay(node, (lpTime->wDayOfWeek + 6) % 7); + else if (count == 3) + szAdd = GetShortDay(node, (lpTime->wDayOfWeek + 6) % 7); + else + { + dwVal = lpTime->wDay; + szAdd = buff; + d_dd_formatted = TRUE; + } + break; + + case 'M': + if (count >= 4) + { + LPCWSTR genitive = GetGenitiveMonth(node, lpTime->wMonth - 1); + if (genitive) + { + if (d_dd_formatted) + { + szAdd = genitive; + break; + } + else + { + LPCWSTR format = lpFormat; + /* Look forward now, if next format pattern is for day genitive + name should be used */ + while (*format) + { + /* Skip parts within markers */ + if (IsLiteralMarker(*format)) + { + ++format; + while (*format) + { + if (IsLiteralMarker(*format)) + { + ++format; + if (!IsLiteralMarker(*format)) break; + } + } + } + if (*format != ' ') break; + ++format; + } + /* Only numeric day form matters */ + if (*format && *format == 'd') + { + INT dcount = 1; + while (*++format == 'd') dcount++; + if (dcount < 3) + { + szAdd = genitive; + break; + } + } + } + } + szAdd = GetLongMonth(node, lpTime->wMonth - 1); + } + else if (count == 3) + szAdd = GetShortMonth(node, lpTime->wMonth - 1); + else + { + dwVal = lpTime->wMonth; + szAdd = buff; + } + break; + + case 'y': + if (count >= 4) + { + count = 4; + dwVal = lpTime->wYear; + } + else + { + count = count > 2 ? 2 : count; + dwVal = lpTime->wYear % 100; + } + szAdd = buff; + break; + + case 'g': + if (count == 2) + { + /* FIXME: Our GetCalendarInfo() does not yet support CAL_SERASTRING. + * When it is fixed, this string should be cached in 'node'. + */ + FIXME("Should be using GetCalendarInfo(CAL_SERASTRING), defaulting to 'AD'\n"); + buff[0] = 'A'; buff[1] = 'D'; buff[2] = '\0'; + } + else + { + buff[0] = 'g'; buff[1] = '\0'; /* Add a literal 'g' */ + } + szAdd = buff; + break; + + case 'h': + if (!(dwFlags & TIME_FORCE24HOURFORMAT)) + { + count = count > 2 ? 2 : count; + dwVal = lpTime->wHour == 0 ? 12 : (lpTime->wHour - 1) % 12 + 1; + szAdd = buff; + break; + } + /* .. fall through if we are forced to output in 24 hour format */ + + case 'H': + count = count > 2 ? 2 : count; + dwVal = lpTime->wHour; + szAdd = buff; + break; + + case 'm': + if (dwFlags & TIME_NOMINUTESORSECONDS) + { + cchWritten = lastFormatPos; /* Skip */ + bSkipping = TRUE; + } + else + { + count = count > 2 ? 2 : count; + dwVal = lpTime->wMinute; + szAdd = buff; + } + break; + + case 's': + if (dwFlags & (TIME_NOSECONDS|TIME_NOMINUTESORSECONDS)) + { + cchWritten = lastFormatPos; /* Skip */ + bSkipping = TRUE; + } + else + { + count = count > 2 ? 2 : count; + dwVal = lpTime->wSecond; + szAdd = buff; + } + break; + + case 't': + if (dwFlags & TIME_NOTIMEMARKER) + { + cchWritten = lastFormatPos; /* Skip */ + bSkipping = TRUE; + } + else + { + if (count == 1) + szAdd = lpTime->wHour < 12 ? node->szShortAM : node->szShortPM; + else + szAdd = lpTime->wHour < 12 ? GetAM(node) : GetPM(node); + } + break; + } + + if (szAdd == buff && buff[0] == '\0') + { + static const WCHAR fmtW[] = {'%','.','*','d',0}; + /* We have a numeric value to add */ + snprintfW(buff, sizeof(buff)/sizeof(WCHAR), fmtW, count, dwVal); + } + + dwLen = szAdd ? strlenW(szAdd) : 0; + + if (cchOut && dwLen) + { + if (cchWritten + dwLen < cchOut) + memcpy(lpStr + cchWritten, szAdd, dwLen * sizeof(WCHAR)); + else + { + memcpy(lpStr + cchWritten, szAdd, (cchOut - cchWritten) * sizeof(WCHAR)); + goto overrun; + } + } + cchWritten += dwLen; + lastFormatPos = cchWritten; /* Save position of last output format text */ + } + else + { + /* Literal character */ + if (!cchOut) + cchWritten++; /* Count size only */ + else if (cchWritten >= cchOut) + goto overrun; + else if (!bSkipping || *lpFormat == ' ') + { + lpStr[cchWritten] = *lpFormat; + cchWritten++; + } + lpFormat++; + } + } + + /* Final string terminator and sanity check */ + if (cchOut) + { + if (cchWritten >= cchOut) + goto overrun; + else + lpStr[cchWritten] = '\0'; + } + cchWritten++; /* Include terminating NUL */ + + TRACE("returning length=%d, ouput=%s\n", cchWritten, debugstr_w(lpStr)); + return cchWritten; + +overrun: + TRACE("returning 0, (ERROR_INSUFFICIENT_BUFFER)\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + +invalid_parameter: + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + +invalid_flags: + SetLastError(ERROR_INVALID_FLAGS); + return 0; +} + +/****************************************************************************** + * NLS_GetDateTimeFormatA + * + * ASCII wrapper for GetDateFormatA/GetTimeFormatA. + */ +static INT NLS_GetDateTimeFormatA(LCID lcid, DWORD dwFlags, + const SYSTEMTIME* lpTime, + LPCSTR lpFormat, LPSTR lpStr, INT cchOut) +{ + DWORD cp = CP_ACP; + WCHAR szFormat[128], szOut[128]; + INT iRet; + + TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n", lcid, dwFlags, lpTime, + debugstr_a(lpFormat), lpStr, cchOut); + + if (NLS_IsUnicodeOnlyLcid(lcid)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!(dwFlags & LOCALE_USE_CP_ACP)) + { + const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags); + if (!node) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + cp = node->dwCodePage; + } + + if (lpFormat) + MultiByteToWideChar(cp, 0, lpFormat, -1, szFormat, sizeof(szFormat)/sizeof(WCHAR)); + + if (cchOut > (int)(sizeof(szOut)/sizeof(WCHAR))) + cchOut = sizeof(szOut)/sizeof(WCHAR); + + szOut[0] = '\0'; + + iRet = NLS_GetDateTimeFormatW(lcid, dwFlags, lpTime, lpFormat ? szFormat : NULL, + lpStr ? szOut : NULL, cchOut); + + if (lpStr) + { + if (szOut[0]) + WideCharToMultiByte(cp, 0, szOut, iRet ? -1 : cchOut, lpStr, cchOut, 0, 0); + else if (cchOut && iRet) + *lpStr = '\0'; + } + return iRet; +} + +/****************************************************************************** + * GetDateFormatA [KERNEL32.@] + * + * Format a date for a given locale. + * + * PARAMS + * lcid [I] Locale to format for + * dwFlags [I] LOCALE_ and DATE_ flags from "winnls.h" + * lpTime [I] Date to format + * lpFormat [I] Format string, or NULL to use the system defaults + * lpDateStr [O] Destination for formatted string + * cchOut [I] Size of lpDateStr, or 0 to calculate the resulting size + * + * NOTES + * - If lpFormat is NULL, lpDateStr will be formatted according to the format + * details returned by GetLocaleInfoA() and modified by dwFlags. + * - lpFormat is a string of characters and formatting tokens. Any characters + * in the string are copied verbatim to lpDateStr, with tokens being replaced + * by the date values they represent. + * - The following tokens have special meanings in a date format string: + *| Token Meaning + *| ----- ------- + *| d Single digit day of the month (no leading 0) + *| dd Double digit day of the month + *| ddd Short name for the day of the week + *| dddd Long name for the day of the week + *| M Single digit month of the year (no leading 0) + *| MM Double digit month of the year + *| MMM Short name for the month of the year + *| MMMM Long name for the month of the year + *| y Double digit year number (no leading 0) + *| yy Double digit year number + *| yyyy Four digit year number + *| gg Era string, for example 'AD'. + * - To output any literal character that could be misidentified as a token, + * enclose it in single quotes. + * - The Ascii version of this function fails if lcid is Unicode only. + * + * RETURNS + * Success: The number of character written to lpDateStr, or that would + * have been written, if cchOut is 0. + * Failure: 0. Use GetLastError() to determine the cause. + */ +INT WINAPI GetDateFormatA( LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime, + LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut) +{ + TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n",lcid, dwFlags, lpTime, + debugstr_a(lpFormat), lpDateStr, cchOut); + + return NLS_GetDateTimeFormatA(lcid, dwFlags | DATE_DATEVARSONLY, lpTime, + lpFormat, lpDateStr, cchOut); +} + + +/****************************************************************************** + * GetDateFormatW [KERNEL32.@] + * + * See GetDateFormatA. + */ +INT WINAPI GetDateFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime, + LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut) +{ + TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n", lcid, dwFlags, lpTime, + debugstr_w(lpFormat), lpDateStr, cchOut); + + return NLS_GetDateTimeFormatW(lcid, dwFlags|DATE_DATEVARSONLY, lpTime, + lpFormat, lpDateStr, cchOut); +} + +/****************************************************************************** + * GetTimeFormatA [KERNEL32.@] + * + * Format a time for a given locale. + * + * PARAMS + * lcid [I] Locale to format for + * dwFlags [I] LOCALE_ and TIME_ flags from "winnls.h" + * lpTime [I] Time to format + * lpFormat [I] Formatting overrides + * lpTimeStr [O] Destination for formatted string + * cchOut [I] Size of lpTimeStr, or 0 to calculate the resulting size + * + * NOTES + * - If lpFormat is NULL, lpszValue will be formatted according to the format + * details returned by GetLocaleInfoA() and modified by dwFlags. + * - lpFormat is a string of characters and formatting tokens. Any characters + * in the string are copied verbatim to lpTimeStr, with tokens being replaced + * by the time values they represent. + * - The following tokens have special meanings in a time format string: + *| Token Meaning + *| ----- ------- + *| h Hours with no leading zero (12-hour clock) + *| hh Hours with full two digits (12-hour clock) + *| H Hours with no leading zero (24-hour clock) + *| HH Hours with full two digits (24-hour clock) + *| m Minutes with no leading zero + *| mm Minutes with full two digits + *| s Seconds with no leading zero + *| ss Seconds with full two digits + *| t Short time marker (e.g. "A" or "P") + *| tt Long time marker (e.g. "AM", "PM") + * - To output any literal character that could be misidentified as a token, + * enclose it in single quotes. + * - The Ascii version of this function fails if lcid is Unicode only. + * + * RETURNS + * Success: The number of character written to lpTimeStr, or that would + * have been written, if cchOut is 0. + * Failure: 0. Use GetLastError() to determine the cause. + */ +INT WINAPI GetTimeFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime, + LPCSTR lpFormat, LPSTR lpTimeStr, INT cchOut) +{ + TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n",lcid, dwFlags, lpTime, + debugstr_a(lpFormat), lpTimeStr, cchOut); + + return NLS_GetDateTimeFormatA(lcid, dwFlags|TIME_TIMEVARSONLY, lpTime, + lpFormat, lpTimeStr, cchOut); +} + +/****************************************************************************** + * GetTimeFormatW [KERNEL32.@] + * + * See GetTimeFormatA. + */ +INT WINAPI GetTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime, + LPCWSTR lpFormat, LPWSTR lpTimeStr, INT cchOut) +{ + TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n",lcid, dwFlags, lpTime, + debugstr_w(lpFormat), lpTimeStr, cchOut); + + return NLS_GetDateTimeFormatW(lcid, dwFlags|TIME_TIMEVARSONLY, lpTime, + lpFormat, lpTimeStr, cchOut); +} + +/************************************************************************** + * GetNumberFormatA (KERNEL32.@) + * + * Format a number string for a given locale. + * + * PARAMS + * lcid [I] Locale to format for + * dwFlags [I] LOCALE_ flags from "winnls.h" + * lpszValue [I] String to format + * lpFormat [I] Formatting overrides + * lpNumberStr [O] Destination for formatted string + * cchOut [I] Size of lpNumberStr, or 0 to calculate the resulting size + * + * NOTES + * - lpszValue can contain only '0' - '9', '-' and '.'. + * - If lpFormat is non-NULL, dwFlags must be 0. In this case lpszValue will + * be formatted according to the format details returned by GetLocaleInfoA(). + * - This function rounds the number string if the number of decimals exceeds the + * locales normal number of decimal places. + * - If cchOut is 0, this function does not write to lpNumberStr. + * - The Ascii version of this function fails if lcid is Unicode only. + * + * RETURNS + * Success: The number of character written to lpNumberStr, or that would + * have been written, if cchOut is 0. + * Failure: 0. Use GetLastError() to determine the cause. + */ +INT WINAPI GetNumberFormatA(LCID lcid, DWORD dwFlags, + LPCSTR lpszValue, const NUMBERFMTA *lpFormat, + LPSTR lpNumberStr, int cchOut) +{ + DWORD cp = CP_ACP; + WCHAR szDec[8], szGrp[8], szIn[128], szOut[128]; + NUMBERFMTW fmt; + const NUMBERFMTW *pfmt = NULL; + INT iRet; + + TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_a(lpszValue), + lpFormat, lpNumberStr, cchOut); + + if (NLS_IsUnicodeOnlyLcid(lcid)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!(dwFlags & LOCALE_USE_CP_ACP)) + { + const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags); + if (!node) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + cp = node->dwCodePage; + } + + if (lpFormat) + { + memcpy(&fmt, lpFormat, sizeof(fmt)); + pfmt = &fmt; + if (lpFormat->lpDecimalSep) + { + MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, sizeof(szDec)/sizeof(WCHAR)); + fmt.lpDecimalSep = szDec; + } + if (lpFormat->lpThousandSep) + { + MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, sizeof(szGrp)/sizeof(WCHAR)); + fmt.lpThousandSep = szGrp; + } + } + + if (lpszValue) + MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, sizeof(szIn)/sizeof(WCHAR)); + + if (cchOut > (int)(sizeof(szOut)/sizeof(WCHAR))) + cchOut = sizeof(szOut)/sizeof(WCHAR); + + szOut[0] = '\0'; + + iRet = GetNumberFormatW(lcid, dwFlags, lpszValue ? szIn : NULL, pfmt, + lpNumberStr ? szOut : NULL, cchOut); + + if (szOut[0] && lpNumberStr) + WideCharToMultiByte(cp, 0, szOut, -1, lpNumberStr, cchOut, 0, 0); + return iRet; +} + +/* Number parsing state flags */ +#define NF_ISNEGATIVE 0x1 /* '-' found */ +#define NF_ISREAL 0x2 /* '.' found */ +#define NF_DIGITS 0x4 /* '0'-'9' found */ +#define NF_DIGITS_OUT 0x8 /* Digits before the '.' found */ +#define NF_ROUND 0x10 /* Number needs to be rounded */ + +/* Formatting options for Numbers */ +#define NLS_NEG_PARENS 0 /* "(1.1)" */ +#define NLS_NEG_LEFT 1 /* "-1.1" */ +#define NLS_NEG_LEFT_SPACE 2 /* "- 1.1" */ +#define NLS_NEG_RIGHT 3 /* "1.1-" */ +#define NLS_NEG_RIGHT_SPACE 4 /* "1.1 -" */ + +/************************************************************************** + * GetNumberFormatW (KERNEL32.@) + * + * See GetNumberFormatA. + */ +INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, + LPCWSTR lpszValue, const NUMBERFMTW *lpFormat, + LPWSTR lpNumberStr, int cchOut) +{ + WCHAR szBuff[128], *szOut = szBuff + sizeof(szBuff) / sizeof(WCHAR) - 1; + WCHAR szNegBuff[8]; + const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc; + DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0; + INT iRet; + + TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue), + lpFormat, lpNumberStr, cchOut); + + if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpNumberStr) || + !IsValidLocale(lcid, 0) || + (lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep))) + { + goto error; + } + + if (!lpFormat) + { + const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags); + + if (!node) + goto error; + lpFormat = &node->fmt; + lpszNegStart = lpszNeg = GetNegative(node); + } + else + { + GetLocaleInfoW(lcid, LOCALE_SNEGATIVESIGN|(dwFlags & LOCALE_NOUSEROVERRIDE), + szNegBuff, sizeof(szNegBuff)/sizeof(WCHAR)); + lpszNegStart = lpszNeg = szNegBuff; + } + lpszNeg = lpszNeg + strlenW(lpszNeg) - 1; + + dwFlags &= (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP); + + /* Format the number backwards into a temporary buffer */ + + szSrc = lpszValue; + *szOut-- = '\0'; + + /* Check the number for validity */ + while (*szSrc) + { + if (*szSrc >= '0' && *szSrc <= '9') + { + dwState |= NF_DIGITS; + if (dwState & NF_ISREAL) + dwDecimals++; + } + else if (*szSrc == '-') + { + if (dwState) + goto error; /* '-' not first character */ + dwState |= NF_ISNEGATIVE; + } + else if (*szSrc == '.') + { + if (dwState & NF_ISREAL) + goto error; /* More than one '.' */ + dwState |= NF_ISREAL; + } + else + goto error; /* Invalid char */ + szSrc++; + } + szSrc--; /* Point to last character */ + + if (!(dwState & NF_DIGITS)) + goto error; /* No digits */ + + /* Add any trailing negative sign */ + if (dwState & NF_ISNEGATIVE) + { + switch (lpFormat->NegativeOrder) + { + case NLS_NEG_PARENS: + *szOut-- = ')'; + break; + case NLS_NEG_RIGHT: + case NLS_NEG_RIGHT_SPACE: + while (lpszNeg >= lpszNegStart) + *szOut-- = *lpszNeg--; + if (lpFormat->NegativeOrder == NLS_NEG_RIGHT_SPACE) + *szOut-- = ' '; + break; + } + } + + /* Copy all digits up to the decimal point */ + if (!lpFormat->NumDigits) + { + if (dwState & NF_ISREAL) + { + while (*szSrc != '.') /* Don't write any decimals or a separator */ + { + if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND))) + dwState |= NF_ROUND; + else + dwState &= ~NF_ROUND; + szSrc--; + } + szSrc--; + } + } + else + { + LPWSTR lpszDec = lpFormat->lpDecimalSep + strlenW(lpFormat->lpDecimalSep) - 1; + + if (dwDecimals <= lpFormat->NumDigits) + { + dwDecimals = lpFormat->NumDigits - dwDecimals; + while (dwDecimals--) + *szOut-- = '0'; /* Pad to correct number of dp */ + } + else + { + dwDecimals -= lpFormat->NumDigits; + /* Skip excess decimals, and determine if we have to round the number */ + while (dwDecimals--) + { + if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND))) + dwState |= NF_ROUND; + else + dwState &= ~NF_ROUND; + szSrc--; + } + } + + if (dwState & NF_ISREAL) + { + while (*szSrc != '.') + { + if (dwState & NF_ROUND) + { + if (*szSrc == '9') + *szOut-- = '0'; /* continue rounding */ + else + { + dwState &= ~NF_ROUND; + *szOut-- = (*szSrc)+1; + } + szSrc--; + } + else + *szOut-- = *szSrc--; /* Write existing decimals */ + } + szSrc--; /* Skip '.' */ + } + + while (lpszDec >= lpFormat->lpDecimalSep) + *szOut-- = *lpszDec--; /* Write decimal separator */ + } + + dwGroupCount = lpFormat->Grouping == 32 ? 3 : lpFormat->Grouping; + + /* Write the remaining whole number digits, including grouping chars */ + while (szSrc >= lpszValue && *szSrc >= '0' && *szSrc <= '9') + { + if (dwState & NF_ROUND) + { + if (*szSrc == '9') + *szOut-- = '0'; /* continue rounding */ + else + { + dwState &= ~NF_ROUND; + *szOut-- = (*szSrc)+1; + } + szSrc--; + } + else + *szOut-- = *szSrc--; + + dwState |= NF_DIGITS_OUT; + dwCurrentGroupCount++; + if (szSrc >= lpszValue && dwCurrentGroupCount == dwGroupCount && *szSrc != '-') + { + LPWSTR lpszGrp = lpFormat->lpThousandSep + strlenW(lpFormat->lpThousandSep) - 1; + + while (lpszGrp >= lpFormat->lpThousandSep) + *szOut-- = *lpszGrp--; /* Write grouping char */ + + dwCurrentGroupCount = 0; + if (lpFormat->Grouping == 32) + dwGroupCount = 2; /* Indic grouping: 3 then 2 */ + } + } + if (dwState & NF_ROUND) + { + *szOut-- = '1'; /* e.g. .6 > 1.0 */ + } + else if (!(dwState & NF_DIGITS_OUT) && lpFormat->LeadingZero) + *szOut-- = '0'; /* Add leading 0 if we have no digits before the decimal point */ + + /* Add any leading negative sign */ + if (dwState & NF_ISNEGATIVE) + { + switch (lpFormat->NegativeOrder) + { + case NLS_NEG_PARENS: + *szOut-- = '('; + break; + case NLS_NEG_LEFT_SPACE: + *szOut-- = ' '; + /* Fall through */ + case NLS_NEG_LEFT: + while (lpszNeg >= lpszNegStart) + *szOut-- = *lpszNeg--; + break; + } + } + szOut++; + + iRet = strlenW(szOut) + 1; + if (cchOut) + { + if (iRet <= cchOut) + memcpy(lpNumberStr, szOut, iRet * sizeof(WCHAR)); + else + { + memcpy(lpNumberStr, szOut, cchOut * sizeof(WCHAR)); + lpNumberStr[cchOut - 1] = '\0'; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + iRet = 0; + } + } + return iRet; + +error: + SetLastError(lpFormat && dwFlags ? ERROR_INVALID_FLAGS : ERROR_INVALID_PARAMETER); + return 0; +} + +/************************************************************************** + * GetCurrencyFormatA (KERNEL32.@) + * + * Format a currency string for a given locale. + * + * PARAMS + * lcid [I] Locale to format for + * dwFlags [I] LOCALE_ flags from "winnls.h" + * lpszValue [I] String to format + * lpFormat [I] Formatting overrides + * lpCurrencyStr [O] Destination for formatted string + * cchOut [I] Size of lpCurrencyStr, or 0 to calculate the resulting size + * + * NOTES + * - lpszValue can contain only '0' - '9', '-' and '.'. + * - If lpFormat is non-NULL, dwFlags must be 0. In this case lpszValue will + * be formatted according to the format details returned by GetLocaleInfoA(). + * - This function rounds the currency if the number of decimals exceeds the + * locales number of currency decimal places. + * - If cchOut is 0, this function does not write to lpCurrencyStr. + * - The Ascii version of this function fails if lcid is Unicode only. + * + * RETURNS + * Success: The number of character written to lpNumberStr, or that would + * have been written, if cchOut is 0. + * Failure: 0. Use GetLastError() to determine the cause. + */ +INT WINAPI GetCurrencyFormatA(LCID lcid, DWORD dwFlags, + LPCSTR lpszValue, const CURRENCYFMTA *lpFormat, + LPSTR lpCurrencyStr, int cchOut) +{ + DWORD cp = CP_ACP; + WCHAR szDec[8], szGrp[8], szCy[8], szIn[128], szOut[128]; + CURRENCYFMTW fmt; + const CURRENCYFMTW *pfmt = NULL; + INT iRet; + + TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_a(lpszValue), + lpFormat, lpCurrencyStr, cchOut); + + if (NLS_IsUnicodeOnlyLcid(lcid)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!(dwFlags & LOCALE_USE_CP_ACP)) + { + const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags); + if (!node) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + cp = node->dwCodePage; + } + + if (lpFormat) + { + memcpy(&fmt, lpFormat, sizeof(fmt)); + pfmt = &fmt; + if (lpFormat->lpDecimalSep) + { + MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, sizeof(szDec)/sizeof(WCHAR)); + fmt.lpDecimalSep = szDec; + } + if (lpFormat->lpThousandSep) + { + MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, sizeof(szGrp)/sizeof(WCHAR)); + fmt.lpThousandSep = szGrp; + } + if (lpFormat->lpCurrencySymbol) + { + MultiByteToWideChar(cp, 0, lpFormat->lpCurrencySymbol, -1, szCy, sizeof(szCy)/sizeof(WCHAR)); + fmt.lpCurrencySymbol = szCy; + } + } + + if (lpszValue) + MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, sizeof(szIn)/sizeof(WCHAR)); + + if (cchOut > (int)(sizeof(szOut)/sizeof(WCHAR))) + cchOut = sizeof(szOut)/sizeof(WCHAR); + + szOut[0] = '\0'; + + iRet = GetCurrencyFormatW(lcid, dwFlags, lpszValue ? szIn : NULL, pfmt, + lpCurrencyStr ? szOut : NULL, cchOut); + + if (szOut[0] && lpCurrencyStr) + WideCharToMultiByte(cp, 0, szOut, -1, lpCurrencyStr, cchOut, 0, 0); + return iRet; +} + +/* Formatting states for Currencies. We use flags to avoid code duplication. */ +#define CF_PARENS 0x1 /* Parentheses */ +#define CF_MINUS_LEFT 0x2 /* '-' to the left */ +#define CF_MINUS_RIGHT 0x4 /* '-' to the right */ +#define CF_MINUS_BEFORE 0x8 /* '-' before '$' */ +#define CF_CY_LEFT 0x10 /* '$' to the left */ +#define CF_CY_RIGHT 0x20 /* '$' to the right */ +#define CF_CY_SPACE 0x40 /* ' ' by '$' */ + +/************************************************************************** + * GetCurrencyFormatW (KERNEL32.@) + * + * See GetCurrencyFormatA. + */ +INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags, + LPCWSTR lpszValue, const CURRENCYFMTW *lpFormat, + LPWSTR lpCurrencyStr, int cchOut) +{ + static const BYTE NLS_NegCyFormats[16] = + { + CF_PARENS|CF_CY_LEFT, /* ($1.1) */ + CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT, /* -$1.1 */ + CF_MINUS_LEFT|CF_CY_LEFT, /* $-1.1 */ + CF_MINUS_RIGHT|CF_CY_LEFT, /* $1.1- */ + CF_PARENS|CF_CY_RIGHT, /* (1.1$) */ + CF_MINUS_LEFT|CF_CY_RIGHT, /* -1.1$ */ + CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT, /* 1.1-$ */ + CF_MINUS_RIGHT|CF_CY_RIGHT, /* 1.1$- */ + CF_MINUS_LEFT|CF_CY_RIGHT|CF_CY_SPACE, /* -1.1 $ */ + CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT|CF_CY_SPACE, /* -$ 1.1 */ + CF_MINUS_RIGHT|CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $- */ + CF_MINUS_RIGHT|CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1- */ + CF_MINUS_LEFT|CF_CY_LEFT|CF_CY_SPACE, /* $ -1.1 */ + CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT|CF_CY_SPACE, /* 1.1- $ */ + CF_PARENS|CF_CY_LEFT|CF_CY_SPACE, /* ($ 1.1) */ + CF_PARENS|CF_CY_RIGHT|CF_CY_SPACE, /* (1.1 $) */ + }; + static const BYTE NLS_PosCyFormats[4] = + { + CF_CY_LEFT, /* $1.1 */ + CF_CY_RIGHT, /* 1.1$ */ + CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1 */ + CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $ */ + }; + WCHAR szBuff[128], *szOut = szBuff + sizeof(szBuff) / sizeof(WCHAR) - 1; + WCHAR szNegBuff[8]; + const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc, *lpszCy, *lpszCyStart; + DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0, dwFmt; + INT iRet; + + TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue), + lpFormat, lpCurrencyStr, cchOut); + + if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpCurrencyStr) || + !IsValidLocale(lcid, 0) || + (lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep || + !lpFormat->lpCurrencySymbol || lpFormat->NegativeOrder > 15 || + lpFormat->PositiveOrder > 3))) + { + goto error; + } + + if (!lpFormat) + { + const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags); + + if (!node) + goto error; + + lpFormat = &node->cyfmt; + lpszNegStart = lpszNeg = GetNegative(node); + } + else + { + GetLocaleInfoW(lcid, LOCALE_SNEGATIVESIGN|(dwFlags & LOCALE_NOUSEROVERRIDE), + szNegBuff, sizeof(szNegBuff)/sizeof(WCHAR)); + lpszNegStart = lpszNeg = szNegBuff; + } + dwFlags &= (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP); + + lpszNeg = lpszNeg + strlenW(lpszNeg) - 1; + lpszCyStart = lpFormat->lpCurrencySymbol; + lpszCy = lpszCyStart + strlenW(lpszCyStart) - 1; + + /* Format the currency backwards into a temporary buffer */ + + szSrc = lpszValue; + *szOut-- = '\0'; + + /* Check the number for validity */ + while (*szSrc) + { + if (*szSrc >= '0' && *szSrc <= '9') + { + dwState |= NF_DIGITS; + if (dwState & NF_ISREAL) + dwDecimals++; + } + else if (*szSrc == '-') + { + if (dwState) + goto error; /* '-' not first character */ + dwState |= NF_ISNEGATIVE; + } + else if (*szSrc == '.') + { + if (dwState & NF_ISREAL) + goto error; /* More than one '.' */ + dwState |= NF_ISREAL; + } + else + goto error; /* Invalid char */ + szSrc++; + } + szSrc--; /* Point to last character */ + + if (!(dwState & NF_DIGITS)) + goto error; /* No digits */ + + if (dwState & NF_ISNEGATIVE) + dwFmt = NLS_NegCyFormats[lpFormat->NegativeOrder]; + else + dwFmt = NLS_PosCyFormats[lpFormat->PositiveOrder]; + + /* Add any trailing negative or currency signs */ + if (dwFmt & CF_PARENS) + *szOut-- = ')'; + + while (dwFmt & (CF_MINUS_RIGHT|CF_CY_RIGHT)) + { + switch (dwFmt & (CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT)) + { + case CF_MINUS_RIGHT: + case CF_MINUS_RIGHT|CF_CY_RIGHT: + while (lpszNeg >= lpszNegStart) + *szOut-- = *lpszNeg--; + dwFmt &= ~CF_MINUS_RIGHT; + break; + + case CF_CY_RIGHT: + case CF_MINUS_BEFORE|CF_CY_RIGHT: + case CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT: + while (lpszCy >= lpszCyStart) + *szOut-- = *lpszCy--; + if (dwFmt & CF_CY_SPACE) + *szOut-- = ' '; + dwFmt &= ~(CF_CY_RIGHT|CF_MINUS_BEFORE); + break; + } + } + + /* Copy all digits up to the decimal point */ + if (!lpFormat->NumDigits) + { + if (dwState & NF_ISREAL) + { + while (*szSrc != '.') /* Don't write any decimals or a separator */ + { + if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND))) + dwState |= NF_ROUND; + else + dwState &= ~NF_ROUND; + szSrc--; + } + szSrc--; + } + } + else + { + LPWSTR lpszDec = lpFormat->lpDecimalSep + strlenW(lpFormat->lpDecimalSep) - 1; + + if (dwDecimals <= lpFormat->NumDigits) + { + dwDecimals = lpFormat->NumDigits - dwDecimals; + while (dwDecimals--) + *szOut-- = '0'; /* Pad to correct number of dp */ + } + else + { + dwDecimals -= lpFormat->NumDigits; + /* Skip excess decimals, and determine if we have to round the number */ + while (dwDecimals--) + { + if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND))) + dwState |= NF_ROUND; + else + dwState &= ~NF_ROUND; + szSrc--; + } + } + + if (dwState & NF_ISREAL) + { + while (*szSrc != '.') + { + if (dwState & NF_ROUND) + { + if (*szSrc == '9') + *szOut-- = '0'; /* continue rounding */ + else + { + dwState &= ~NF_ROUND; + *szOut-- = (*szSrc)+1; + } + szSrc--; + } + else + *szOut-- = *szSrc--; /* Write existing decimals */ + } + szSrc--; /* Skip '.' */ + } + while (lpszDec >= lpFormat->lpDecimalSep) + *szOut-- = *lpszDec--; /* Write decimal separator */ + } + + dwGroupCount = lpFormat->Grouping; + + /* Write the remaining whole number digits, including grouping chars */ + while (szSrc >= lpszValue && *szSrc >= '0' && *szSrc <= '9') + { + if (dwState & NF_ROUND) + { + if (*szSrc == '9') + *szOut-- = '0'; /* continue rounding */ + else + { + dwState &= ~NF_ROUND; + *szOut-- = (*szSrc)+1; + } + szSrc--; + } + else + *szOut-- = *szSrc--; + + dwState |= NF_DIGITS_OUT; + dwCurrentGroupCount++; + if (szSrc >= lpszValue && dwCurrentGroupCount == dwGroupCount && *szSrc != '-') + { + LPWSTR lpszGrp = lpFormat->lpThousandSep + strlenW(lpFormat->lpThousandSep) - 1; + + while (lpszGrp >= lpFormat->lpThousandSep) + *szOut-- = *lpszGrp--; /* Write grouping char */ + + dwCurrentGroupCount = 0; + } + } + if (dwState & NF_ROUND) + *szOut-- = '1'; /* e.g. .6 > 1.0 */ + else if (!(dwState & NF_DIGITS_OUT) && lpFormat->LeadingZero) + *szOut-- = '0'; /* Add leading 0 if we have no digits before the decimal point */ + + /* Add any leading negative or currency sign */ + while (dwFmt & (CF_MINUS_LEFT|CF_CY_LEFT)) + { + switch (dwFmt & (CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT)) + { + case CF_MINUS_LEFT: + case CF_MINUS_LEFT|CF_CY_LEFT: + while (lpszNeg >= lpszNegStart) + *szOut-- = *lpszNeg--; + dwFmt &= ~CF_MINUS_LEFT; + break; + + case CF_CY_LEFT: + case CF_CY_LEFT|CF_MINUS_BEFORE: + case CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT: + if (dwFmt & CF_CY_SPACE) + *szOut-- = ' '; + while (lpszCy >= lpszCyStart) + *szOut-- = *lpszCy--; + dwFmt &= ~(CF_CY_LEFT|CF_MINUS_BEFORE); + break; + } + } + if (dwFmt & CF_PARENS) + *szOut-- = '('; + szOut++; + + iRet = strlenW(szOut) + 1; + if (cchOut) + { + if (iRet <= cchOut) + memcpy(lpCurrencyStr, szOut, iRet * sizeof(WCHAR)); + else + { + memcpy(lpCurrencyStr, szOut, cchOut * sizeof(WCHAR)); + lpCurrencyStr[cchOut - 1] = '\0'; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + iRet = 0; + } + } + return iRet; + +error: + SetLastError(lpFormat && dwFlags ? ERROR_INVALID_FLAGS : ERROR_INVALID_PARAMETER); + return 0; +} + +/* FIXME: Everything below here needs to move somewhere else along with the + * other EnumXXX functions, when a method for storing resources for + * alternate calendars is determined. + */ + +/************************************************************************** + * EnumDateFormatsExA (KERNEL32.@) + * + * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle + * LOCALE_NOUSEROVERRIDE here as well? + */ +BOOL WINAPI EnumDateFormatsExA(DATEFMT_ENUMPROCEXA proc, LCID lcid, DWORD flags) +{ + CALID cal_id; + char buf[256]; + + if (!proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!GetLocaleInfoW(lcid, LOCALE_ICALENDARTYPE|LOCALE_RETURN_NUMBER, (LPWSTR)&cal_id, sizeof(cal_id)/sizeof(WCHAR))) + return FALSE; + + switch (flags & ~LOCALE_USE_CP_ACP) + { + case 0: + case DATE_SHORTDATE: + if (GetLocaleInfoA(lcid, LOCALE_SSHORTDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf, cal_id); + break; + + case DATE_LONGDATE: + if (GetLocaleInfoA(lcid, LOCALE_SLONGDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf, cal_id); + break; + + case DATE_YEARMONTH: + if (GetLocaleInfoA(lcid, LOCALE_SYEARMONTH | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf, cal_id); + break; + + default: + FIXME("Unknown date format (%d)\n", flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} + +/************************************************************************** + * EnumDateFormatsExW (KERNEL32.@) + */ +BOOL WINAPI EnumDateFormatsExW(DATEFMT_ENUMPROCEXW proc, LCID lcid, DWORD flags) +{ + CALID cal_id; + WCHAR buf[256]; + + if (!proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!GetLocaleInfoW(lcid, LOCALE_ICALENDARTYPE|LOCALE_RETURN_NUMBER, (LPWSTR)&cal_id, sizeof(cal_id)/sizeof(WCHAR))) + return FALSE; + + switch (flags & ~LOCALE_USE_CP_ACP) + { + case 0: + case DATE_SHORTDATE: + if (GetLocaleInfoW(lcid, LOCALE_SSHORTDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf, cal_id); + break; + + case DATE_LONGDATE: + if (GetLocaleInfoW(lcid, LOCALE_SLONGDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf, cal_id); + break; + + case DATE_YEARMONTH: + if (GetLocaleInfoW(lcid, LOCALE_SYEARMONTH | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf, cal_id); + break; + + default: + FIXME("Unknown date format (%d)\n", flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} + +/************************************************************************** + * EnumDateFormatsA (KERNEL32.@) + * + * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle + * LOCALE_NOUSEROVERRIDE here as well? + */ +BOOL WINAPI EnumDateFormatsA(DATEFMT_ENUMPROCA proc, LCID lcid, DWORD flags) +{ + char buf[256]; + + if (!proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch (flags & ~LOCALE_USE_CP_ACP) + { + case 0: + case DATE_SHORTDATE: + if (GetLocaleInfoA(lcid, LOCALE_SSHORTDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + case DATE_LONGDATE: + if (GetLocaleInfoA(lcid, LOCALE_SLONGDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + case DATE_YEARMONTH: + if (GetLocaleInfoA(lcid, LOCALE_SYEARMONTH | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + default: + FIXME("Unknown date format (%d)\n", flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} + +/************************************************************************** + * EnumDateFormatsW (KERNEL32.@) + */ +BOOL WINAPI EnumDateFormatsW(DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags) +{ + WCHAR buf[256]; + + if (!proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch (flags & ~LOCALE_USE_CP_ACP) + { + case 0: + case DATE_SHORTDATE: + if (GetLocaleInfoW(lcid, LOCALE_SSHORTDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + case DATE_LONGDATE: + if (GetLocaleInfoW(lcid, LOCALE_SLONGDATE | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + case DATE_YEARMONTH: + if (GetLocaleInfoW(lcid, LOCALE_SYEARMONTH | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + default: + FIXME("Unknown date format (%d)\n", flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} + +/************************************************************************** + * EnumTimeFormatsA (KERNEL32.@) + * + * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle + * LOCALE_NOUSEROVERRIDE here as well? + */ +BOOL WINAPI EnumTimeFormatsA(TIMEFMT_ENUMPROCA proc, LCID lcid, DWORD flags) +{ + char buf[256]; + + if (!proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch (flags & ~LOCALE_USE_CP_ACP) + { + case 0: + if (GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + default: + FIXME("Unknown time format (%d)\n", flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} + +/************************************************************************** + * EnumTimeFormatsW (KERNEL32.@) + */ +BOOL WINAPI EnumTimeFormatsW(TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags) +{ + WCHAR buf[256]; + + if (!proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch (flags & ~LOCALE_USE_CP_ACP) + { + case 0: + if (GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT | (flags & LOCALE_USE_CP_ACP), buf, 256)) + proc(buf); + break; + + default: + FIXME("Unknown time format (%d)\n", flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} + +/****************************************************************************** + * NLS_EnumCalendarInfoAW + * Enumerates calendar information for a specified locale. + * + * PARAMS + * calinfoproc [I] Pointer to the callback + * locale [I] The locale for which to retrieve calendar information. + * This parameter can be a locale identifier created by the + * MAKELCID macro, or one of the following values: + * LOCALE_SYSTEM_DEFAULT + * Use the default system locale. + * LOCALE_USER_DEFAULT + * Use the default user locale. + * calendar [I] The calendar for which information is requested, or + * ENUM_ALL_CALENDARS. + * caltype [I] The type of calendar information to be returned. Note + * that only one CALTYPE value can be specified per call + * of this function, except where noted. + * unicode [I] Specifies if the callback expects a unicode string. + * ex [I] Specifies if the callback needs the calendar identifier. + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. Use GetLastError() to determine the cause. + * + * NOTES + * When the ANSI version of this function is used with a Unicode-only LCID, + * the call can succeed because the system uses the system code page. + * However, characters that are undefined in the system code page appear + * in the string as a question mark (?). + * + * TODO + * The above note should be respected by GetCalendarInfoA. + */ +static BOOL NLS_EnumCalendarInfoAW(void *calinfoproc, LCID locale, + CALID calendar, CALTYPE caltype, BOOL unicode, BOOL ex ) +{ + WCHAR *buf, *opt = NULL, *iter = NULL; + BOOL ret = FALSE; + int bufSz = 200; /* the size of the buffer */ + + if (calinfoproc == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + buf = HeapAlloc(GetProcessHeap(), 0, bufSz); + if (buf == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + if (calendar == ENUM_ALL_CALENDARS) + { + int optSz = GetLocaleInfoW(locale, LOCALE_IOPTIONALCALENDAR, NULL, 0); + if (optSz > 1) + { + opt = HeapAlloc(GetProcessHeap(), 0, optSz * sizeof(WCHAR)); + if (opt == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + if (GetLocaleInfoW(locale, LOCALE_IOPTIONALCALENDAR, opt, optSz)) + iter = opt; + } + calendar = NLS_GetLocaleNumber(locale, LOCALE_ICALENDARTYPE); + } + + while (TRUE) /* loop through calendars */ + { + do /* loop until there's no error */ + { + if (unicode) + ret = GetCalendarInfoW(locale, calendar, caltype, buf, bufSz / sizeof(WCHAR), NULL); + else ret = GetCalendarInfoA(locale, calendar, caltype, (CHAR*)buf, bufSz / sizeof(CHAR), NULL); + + if (!ret) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { /* so resize it */ + int newSz; + if (unicode) + newSz = GetCalendarInfoW(locale, calendar, caltype, NULL, 0, NULL) * sizeof(WCHAR); + else newSz = GetCalendarInfoA(locale, calendar, caltype, NULL, 0, NULL) * sizeof(CHAR); + if (bufSz >= newSz) + { + ERR("Buffer resizing disorder: was %d, requested %d.\n", bufSz, newSz); + goto cleanup; + } + bufSz = newSz; + WARN("Buffer too small; resizing to %d bytes.\n", bufSz); + buf = HeapReAlloc(GetProcessHeap(), 0, buf, bufSz); + if (buf == NULL) + goto cleanup; + } else goto cleanup; + } + } while (!ret); + + /* Here we are. We pass the buffer to the correct version of + * the callback. Because it's not the same number of params, + * we must check for Ex, but we don't care about Unicode + * because the buffer is already in the correct format. + */ + if (ex) { + ret = ((CALINFO_ENUMPROCEXW)calinfoproc)(buf, calendar); + } else + ret = ((CALINFO_ENUMPROCW)calinfoproc)(buf); + + if (!ret) { /* the callback told to stop */ + ret = TRUE; + break; + } + + if ((iter == NULL) || (*iter == 0)) /* no more calendars */ + break; + + calendar = 0; + while ((*iter >= '0') && (*iter <= '9')) + calendar = calendar * 10 + *iter++ - '0'; + + if (*iter++ != 0) + { + SetLastError(ERROR_BADDB); + ret = FALSE; + break; + } + } + +cleanup: + HeapFree(GetProcessHeap(), 0, opt); + HeapFree(GetProcessHeap(), 0, buf); + return ret; +} + +/****************************************************************************** + * EnumCalendarInfoA [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, FALSE, FALSE); +} + +/****************************************************************************** + * EnumCalendarInfoW [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoW( CALINFO_ENUMPROCW calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, TRUE, FALSE); +} + +/****************************************************************************** + * EnumCalendarInfoExA [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, FALSE, TRUE); +} + +/****************************************************************************** + * EnumCalendarInfoExW [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoExW( CALINFO_ENUMPROCEXW calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, TRUE, TRUE); +} + +/********************************************************************* + * GetCalendarInfoA (KERNEL32.@) + * + */ +int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, CALTYPE CalType, + LPSTR lpCalData, int cchData, LPDWORD lpValue) +{ + int ret; + LPWSTR lpCalDataW = NULL; + + if (NLS_IsUnicodeOnlyLcid(lcid)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (cchData && + !(lpCalDataW = HeapAlloc(GetProcessHeap(), 0, cchData*sizeof(WCHAR)))) + return 0; + + ret = GetCalendarInfoW(lcid, Calendar, CalType, lpCalDataW, cchData, lpValue); + if(ret && lpCalDataW && lpCalData) + WideCharToMultiByte(CP_ACP, 0, lpCalDataW, cchData, lpCalData, cchData, NULL, NULL); + else if (CalType & CAL_RETURN_NUMBER) + ret *= sizeof(WCHAR); + HeapFree(GetProcessHeap(), 0, lpCalDataW); + + return ret; +} + +/********************************************************************* + * GetCalendarInfoW (KERNEL32.@) + * + */ +int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, + LPWSTR lpCalData, int cchData, LPDWORD lpValue) +{ + if (CalType & CAL_NOUSEROVERRIDE) + FIXME("flag CAL_NOUSEROVERRIDE used, not fully implemented\n"); + if (CalType & CAL_USE_CP_ACP) + FIXME("flag CAL_USE_CP_ACP used, not fully implemented\n"); + + if (CalType & CAL_RETURN_NUMBER) { + if (!lpValue) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + if (lpCalData != NULL) + WARN("lpCalData not NULL (%p) when it should!\n", lpCalData); + if (cchData != 0) + WARN("cchData not 0 (%d) when it should!\n", cchData); + } else { + if (lpValue != NULL) + WARN("lpValue not NULL (%p) when it should!\n", lpValue); + } + + /* FIXME: No verification is made yet wrt Locale + * for the CALTYPES not requiring GetLocaleInfoA */ + switch (CalType & ~(CAL_NOUSEROVERRIDE|CAL_RETURN_NUMBER|CAL_USE_CP_ACP)) { + case CAL_ICALINTVALUE: + FIXME("Unimplemented caltype %d\n", CalType & 0xffff); + return 0; + case CAL_SCALNAME: + FIXME("Unimplemented caltype %d\n", CalType & 0xffff); + return 0; + case CAL_IYEAROFFSETRANGE: + FIXME("Unimplemented caltype %d\n", CalType & 0xffff); + return 0; + case CAL_SERASTRING: + FIXME("Unimplemented caltype %d\n", CalType & 0xffff); + return 0; + case CAL_SSHORTDATE: + return GetLocaleInfoW(Locale, LOCALE_SSHORTDATE, lpCalData, cchData); + case CAL_SLONGDATE: + return GetLocaleInfoW(Locale, LOCALE_SLONGDATE, lpCalData, cchData); + case CAL_SDAYNAME1: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME1, lpCalData, cchData); + case CAL_SDAYNAME2: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME2, lpCalData, cchData); + case CAL_SDAYNAME3: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME3, lpCalData, cchData); + case CAL_SDAYNAME4: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME4, lpCalData, cchData); + case CAL_SDAYNAME5: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME5, lpCalData, cchData); + case CAL_SDAYNAME6: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME6, lpCalData, cchData); + case CAL_SDAYNAME7: + return GetLocaleInfoW(Locale, LOCALE_SDAYNAME7, lpCalData, cchData); + case CAL_SABBREVDAYNAME1: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME1, lpCalData, cchData); + case CAL_SABBREVDAYNAME2: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME2, lpCalData, cchData); + case CAL_SABBREVDAYNAME3: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME3, lpCalData, cchData); + case CAL_SABBREVDAYNAME4: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME4, lpCalData, cchData); + case CAL_SABBREVDAYNAME5: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME5, lpCalData, cchData); + case CAL_SABBREVDAYNAME6: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME6, lpCalData, cchData); + case CAL_SABBREVDAYNAME7: + return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME7, lpCalData, cchData); + case CAL_SMONTHNAME1: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME1, lpCalData, cchData); + case CAL_SMONTHNAME2: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME2, lpCalData, cchData); + case CAL_SMONTHNAME3: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME3, lpCalData, cchData); + case CAL_SMONTHNAME4: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME4, lpCalData, cchData); + case CAL_SMONTHNAME5: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME5, lpCalData, cchData); + case CAL_SMONTHNAME6: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME6, lpCalData, cchData); + case CAL_SMONTHNAME7: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME7, lpCalData, cchData); + case CAL_SMONTHNAME8: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME8, lpCalData, cchData); + case CAL_SMONTHNAME9: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME9, lpCalData, cchData); + case CAL_SMONTHNAME10: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME10, lpCalData, cchData); + case CAL_SMONTHNAME11: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME11, lpCalData, cchData); + case CAL_SMONTHNAME12: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME12, lpCalData, cchData); + case CAL_SMONTHNAME13: + return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME13, lpCalData, cchData); + case CAL_SABBREVMONTHNAME1: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME1, lpCalData, cchData); + case CAL_SABBREVMONTHNAME2: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME2, lpCalData, cchData); + case CAL_SABBREVMONTHNAME3: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME3, lpCalData, cchData); + case CAL_SABBREVMONTHNAME4: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME4, lpCalData, cchData); + case CAL_SABBREVMONTHNAME5: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME5, lpCalData, cchData); + case CAL_SABBREVMONTHNAME6: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME6, lpCalData, cchData); + case CAL_SABBREVMONTHNAME7: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME7, lpCalData, cchData); + case CAL_SABBREVMONTHNAME8: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME8, lpCalData, cchData); + case CAL_SABBREVMONTHNAME9: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME9, lpCalData, cchData); + case CAL_SABBREVMONTHNAME10: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME10, lpCalData, cchData); + case CAL_SABBREVMONTHNAME11: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME11, lpCalData, cchData); + case CAL_SABBREVMONTHNAME12: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME12, lpCalData, cchData); + case CAL_SABBREVMONTHNAME13: + return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME13, lpCalData, cchData); + case CAL_SYEARMONTH: + return GetLocaleInfoW(Locale, LOCALE_SYEARMONTH, lpCalData, cchData); + case CAL_ITWODIGITYEARMAX: + if (CalType & CAL_RETURN_NUMBER) + { + *lpValue = CALINFO_MAX_YEAR; + return sizeof(DWORD) / sizeof(WCHAR); + } + else + { + static const WCHAR fmtW[] = {'%','u',0}; + WCHAR buffer[10]; + int ret = snprintfW( buffer, 10, fmtW, CALINFO_MAX_YEAR ) + 1; + if (!lpCalData) return ret; + if (ret <= cchData) + { + strcpyW( lpCalData, buffer ); + return ret; + } + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return 0; + } + break; + default: + FIXME("Unknown caltype %d\n",CalType & 0xffff); + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + return 0; +} + +/********************************************************************* + * SetCalendarInfoA (KERNEL32.@) + * + */ +int WINAPI SetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData) +{ + FIXME("(%08x,%08x,%08x,%s): stub\n", + Locale, Calendar, CalType, debugstr_a(lpCalData)); + return 0; +} + +/********************************************************************* + * SetCalendarInfoW (KERNEL32.@) + * + * + */ +int WINAPI SetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData) +{ + FIXME("(%08x,%08x,%08x,%s): stub\n", + Locale, Calendar, CalType, debugstr_w(lpCalData)); + return 0; +} diff --git a/dll/win32/kernel32/winnls/string/lcformat_private.h b/dll/win32/kernel32/winnls/string/lcformat_private.h new file mode 100644 index 00000000000..0b00a820cd9 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/lcformat_private.h @@ -0,0 +1,12 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS System Libraries + * FILE: lib/kernel32/misc/lcformat_private.h + * PURPOSE: Win32 Kernel Libary Header + * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org) + */ + +#pragma once + +/*lcformat.c */ +extern BOOL NLS_IsUnicodeOnlyLcid(LCID); diff --git a/dll/win32/kernel32/string/lstring.c b/dll/win32/kernel32/winnls/string/lstring.c similarity index 100% rename from dll/win32/kernel32/string/lstring.c rename to dll/win32/kernel32/winnls/string/lstring.c diff --git a/dll/win32/kernel32/winnls/string/nls.c b/dll/win32/kernel32/winnls/string/nls.c new file mode 100644 index 00000000000..e3f6d244ef1 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/nls.c @@ -0,0 +1,2163 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: dll/win32/kernel32/misc/nls.c + * PURPOSE: National Language Support + * PROGRAMMER: Filip Navara + * Hartmut Birr + * Gunnar Andre Dalsnes + * Thomas Weidenmueller + * UPDATE HISTORY: + * Created 24/08/2004 + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBAL VARIABLES ***********************************************************/ + +/* Sequence length based on the first character. */ +static const char UTF8Length[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xC0 - 0xCF */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xD0 - 0xDF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xE0 - 0xEF */ + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 0, 0 /* 0xF0 - 0xFF */ +}; + +/* First byte mask depending on UTF-8 sequence length. */ +static const unsigned char UTF8Mask[6] = {0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +/* FIXME: Change to HASH table or linear array. */ +static LIST_ENTRY CodePageListHead; +static CODEPAGE_ENTRY AnsiCodePage; +static CODEPAGE_ENTRY OemCodePage; +static RTL_CRITICAL_SECTION CodePageListLock; + +/* FORWARD DECLARATIONS *******************************************************/ + +BOOL WINAPI +GetNlsSectionName(UINT CodePage, UINT Base, ULONG Unknown, + LPSTR BaseName, LPSTR Result, ULONG ResultSize); + +BOOL WINAPI +GetCPFileNameFromRegistry(UINT CodePage, LPWSTR FileName, ULONG FileNameSize); + +/* PRIVATE FUNCTIONS **********************************************************/ + +/** + * @name NlsInit + * + * Internal NLS related stuff initialization. + */ + +BOOL +FASTCALL +NlsInit(VOID) +{ + UNICODE_STRING DirName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + + InitializeListHead(&CodePageListHead); + RtlInitializeCriticalSection(&CodePageListLock); + + /* + * FIXME: Eventually this should be done only for the NLS Server + * process, but since we don't have anything like that (yet?) we + * always try to create the "\Nls" directory here. + */ + RtlInitUnicodeString(&DirName, L"\\Nls"); + + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, + NULL, + NULL); + + if (NT_SUCCESS(NtCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes))) + { + NtClose(Handle); + } + + /* Setup ANSI code page. */ + AnsiCodePage.CodePage = CP_ACP; + AnsiCodePage.SectionHandle = NULL; + AnsiCodePage.SectionMapping = NtCurrentTeb()->ProcessEnvironmentBlock->AnsiCodePageData; + + RtlInitCodePageTable((PUSHORT)AnsiCodePage.SectionMapping, + &AnsiCodePage.CodePageTable); + InsertTailList(&CodePageListHead, &AnsiCodePage.Entry); + + /* Setup OEM code page. */ + OemCodePage.CodePage = CP_OEMCP; + OemCodePage.SectionHandle = NULL; + OemCodePage.SectionMapping = NtCurrentTeb()->ProcessEnvironmentBlock->OemCodePageData; + + RtlInitCodePageTable((PUSHORT)OemCodePage.SectionMapping, + &OemCodePage.CodePageTable); + InsertTailList(&CodePageListHead, &OemCodePage.Entry); + + return TRUE; +} + +/** + * @name NlsUninit + * + * Internal NLS related stuff uninitialization. + */ + +VOID +FASTCALL +NlsUninit(VOID) +{ + PCODEPAGE_ENTRY Current; + + /* Delete the code page list. */ + while (!IsListEmpty(&CodePageListHead)) + { + Current = CONTAINING_RECORD(CodePageListHead.Flink, CODEPAGE_ENTRY, Entry); + if (Current->SectionHandle != NULL) + { + UnmapViewOfFile(Current->SectionMapping); + NtClose(Current->SectionHandle); + } + RemoveHeadList(&CodePageListHead); + } + RtlDeleteCriticalSection(&CodePageListLock); +} + +/** + * @name IntGetLoadedCodePageEntry + * + * Internal function to get structure containing a code page information + * of code page that is already loaded. + * + * @param CodePage + * Number of the code page. Special values like CP_OEMCP, CP_ACP + * or CP_UTF8 aren't allowed. + * + * @return Code page entry or NULL if the specified code page hasn't + * been loaded yet. + */ + +PCODEPAGE_ENTRY +FASTCALL +IntGetLoadedCodePageEntry(UINT CodePage) +{ + LIST_ENTRY *CurrentEntry; + PCODEPAGE_ENTRY Current; + + RtlEnterCriticalSection(&CodePageListLock); + for (CurrentEntry = CodePageListHead.Flink; + CurrentEntry != &CodePageListHead; + CurrentEntry = CurrentEntry->Flink) + { + Current = CONTAINING_RECORD(CurrentEntry, CODEPAGE_ENTRY, Entry); + if (Current->CodePage == CodePage) + { + RtlLeaveCriticalSection(&CodePageListLock); + return Current; + } + } + RtlLeaveCriticalSection(&CodePageListLock); + + return NULL; +} + +/** + * @name IntGetCodePageEntry + * + * Internal function to get structure containing a code page information. + * + * @param CodePage + * Number of the code page. Special values like CP_OEMCP, CP_ACP + * or CP_THREAD_ACP are allowed, but CP_UTF[7/8] isn't. + * + * @return Code page entry. + */ + +PCODEPAGE_ENTRY +FASTCALL +IntGetCodePageEntry(UINT CodePage) +{ + CHAR SectionName[40]; + NTSTATUS Status; + HANDLE SectionHandle = INVALID_HANDLE_VALUE, FileHandle; + PBYTE SectionMapping; + OBJECT_ATTRIBUTES ObjectAttributes; + ANSI_STRING AnsiName; + UNICODE_STRING UnicodeName; + WCHAR FileName[MAX_PATH + 1]; + UINT FileNamePos; + PCODEPAGE_ENTRY CodePageEntry; + + if (CodePage == CP_THREAD_ACP) + { + if (!GetLocaleInfoW(GetThreadLocale(), + LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, + (WCHAR *)&CodePage, + sizeof(CodePage) / sizeof(WCHAR))) + { + /* Last error is set by GetLocaleInfoW. */ + return NULL; + } + } + else if (CodePage == CP_MACCP) + { + if (!GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, + LOCALE_IDEFAULTMACCODEPAGE | LOCALE_RETURN_NUMBER, + (WCHAR *)&CodePage, + sizeof(CodePage) / sizeof(WCHAR))) + { + /* Last error is set by GetLocaleInfoW. */ + return NULL; + } + } + + /* Try searching for loaded page first. */ + CodePageEntry = IntGetLoadedCodePageEntry(CodePage); + if (CodePageEntry != NULL) + { + return CodePageEntry; + } + + /* + * Yes, we really want to lock here. Otherwise it can happen that + * two parallel requests will try to get the entry for the same + * code page and we would load it twice. + */ + RtlEnterCriticalSection(&CodePageListLock); + + /* Generate the section name. */ + if (!GetNlsSectionName(CodePage, + 10, + 0, + "\\Nls\\NlsSectionCP", + SectionName, + sizeof(SectionName))) + { + RtlLeaveCriticalSection(&CodePageListLock); + return NULL; + } + + RtlInitAnsiString(&AnsiName, SectionName); + RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE); + + InitializeObjectAttributes(&ObjectAttributes, &UnicodeName, 0, NULL, NULL); + + /* Try to open the section first */ + Status = NtOpenSection(&SectionHandle, SECTION_MAP_READ, &ObjectAttributes); + + /* If the section doesn't exist, try to create it. */ + if (Status == STATUS_UNSUCCESSFUL || + Status == STATUS_OBJECT_NAME_NOT_FOUND || + Status == STATUS_OBJECT_PATH_NOT_FOUND) + { + FileNamePos = GetSystemDirectoryW(FileName, MAX_PATH); + if (GetCPFileNameFromRegistry(CodePage, + FileName + FileNamePos + 1, + MAX_PATH - FileNamePos - 1)) + { + FileName[FileNamePos] = L'\\'; + FileName[MAX_PATH] = 0; + FileHandle = CreateFileW(FileName, + FILE_GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL); + + Status = NtCreateSection(&SectionHandle, + SECTION_MAP_READ, + &ObjectAttributes, + NULL, + PAGE_READONLY, + SEC_COMMIT, + FileHandle); + + /* HACK: Check if another process was faster + * and already created this section. See bug 3626 for details */ + if (Status == STATUS_OBJECT_NAME_COLLISION) + { + /* Close the file then */ + NtClose(FileHandle); + + /* And open the section */ + Status = NtOpenSection(&SectionHandle, + SECTION_MAP_READ, + &ObjectAttributes); + } + } + } + RtlFreeUnicodeString(&UnicodeName); + + if (!NT_SUCCESS(Status)) + { + RtlLeaveCriticalSection(&CodePageListLock); + return NULL; + } + + SectionMapping = MapViewOfFile(SectionHandle, FILE_MAP_READ, 0, 0, 0); + if (SectionMapping == NULL) + { + NtClose(SectionHandle); + RtlLeaveCriticalSection(&CodePageListLock); + return NULL; + } + + CodePageEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CODEPAGE_ENTRY)); + if (CodePageEntry == NULL) + { + NtClose(SectionHandle); + RtlLeaveCriticalSection(&CodePageListLock); + return NULL; + } + + CodePageEntry->CodePage = CodePage; + CodePageEntry->SectionHandle = SectionHandle; + CodePageEntry->SectionMapping = SectionMapping; + + RtlInitCodePageTable((PUSHORT)SectionMapping, &CodePageEntry->CodePageTable); + + /* Insert the new entry to list and unlock. Uff. */ + InsertTailList(&CodePageListHead, &CodePageEntry->Entry); + RtlLeaveCriticalSection(&CodePageListLock); + + return CodePageEntry; +} + +/** + * @name IntMultiByteToWideCharUTF8 + * + * Internal version of MultiByteToWideChar for UTF8. + * + * @see MultiByteToWideChar + * @todo Add UTF8 validity checks. + */ + +static +INT +WINAPI +IntMultiByteToWideCharUTF8(DWORD Flags, + LPCSTR MultiByteString, + INT MultiByteCount, + LPWSTR WideCharString, + INT WideCharCount) +{ + LPCSTR MbsEnd; + UCHAR Char, Length; + WCHAR WideChar; + LONG Count; + + if (Flags != 0) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + /* Does caller query for output buffer size? */ + if (WideCharCount == 0) + { + MbsEnd = MultiByteString + MultiByteCount; + for (; MultiByteString < MbsEnd; WideCharCount++) + { + Char = *MultiByteString++; + if (Char < 0xC0) + continue; + MultiByteString += UTF8Length[Char - 0x80]; + } + return WideCharCount; + } + + MbsEnd = MultiByteString + MultiByteCount; + for (Count = 0; Count < WideCharCount && MultiByteString < MbsEnd; Count++) + { + Char = *MultiByteString++; + if (Char < 0x80) + { + *WideCharString++ = Char; + continue; + } + Length = UTF8Length[Char - 0x80]; + WideChar = Char & UTF8Mask[Length]; + while (Length && MultiByteString < MbsEnd) + { + WideChar = (WideChar << 6) | (*MultiByteString++ & 0x7f); + Length--; + } + *WideCharString++ = WideChar; + } + + if (MultiByteString < MbsEnd) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + + return Count; +} + +/** + * @name IntMultiByteToWideCharCP + * + * Internal version of MultiByteToWideChar for code page tables. + * + * @see MultiByteToWideChar + * @todo Handle MB_PRECOMPOSED, MB_COMPOSITE, MB_USEGLYPHCHARS and + * DBCS codepages. + */ + +static +INT +WINAPI +IntMultiByteToWideCharCP(UINT CodePage, + DWORD Flags, + LPCSTR MultiByteString, + INT MultiByteCount, + LPWSTR WideCharString, + INT WideCharCount) +{ + PCODEPAGE_ENTRY CodePageEntry; + PCPTABLEINFO CodePageTable; + LPCSTR TempString; + INT TempLength; + + /* Get code page table. */ + CodePageEntry = IntGetCodePageEntry(CodePage); + if (CodePageEntry == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + CodePageTable = &CodePageEntry->CodePageTable; + + /* Different handling for DBCS code pages. */ + if (CodePageTable->MaximumCharacterSize > 1) + { + /* FIXME */ + + UCHAR Char; + USHORT DBCSOffset; + LPCSTR MbsEnd = MultiByteString + MultiByteCount; + INT Count; + + /* Does caller query for output buffer size? */ + if (WideCharCount == 0) + { + for (; MultiByteString < MbsEnd; WideCharCount++) + { + Char = *MultiByteString++; + + if (Char < 0x80) + continue; + + DBCSOffset = CodePageTable->DBCSOffsets[Char]; + + if (!DBCSOffset) + continue; + + if (MultiByteString < MbsEnd) + MultiByteString++; + } + + return WideCharCount; + } + + for (Count = 0; Count < WideCharCount && MultiByteString < MbsEnd; Count++) + { + Char = *MultiByteString++; + + if (Char < 0x80) + { + *WideCharString++ = Char; + continue; + } + + DBCSOffset = CodePageTable->DBCSOffsets[Char]; + + if (!DBCSOffset) + { + *WideCharString++ = CodePageTable->MultiByteTable[Char]; + continue; + } + + if (MultiByteString < MbsEnd) + *WideCharString++ = CodePageTable->DBCSOffsets[DBCSOffset + *(PUCHAR)MultiByteString++]; + } + + if (MultiByteString < MbsEnd) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + return Count; + } + else /* Not DBCS code page */ + { + /* Check for invalid characters. */ + if (Flags & MB_ERR_INVALID_CHARS) + { + for (TempString = MultiByteString, TempLength = MultiByteCount; + TempLength > 0; + TempString++, TempLength--) + { + if (CodePageTable->MultiByteTable[(UCHAR)*TempString] == + CodePageTable->UniDefaultChar && + *TempString != CodePageEntry->CodePageTable.DefaultChar) + { + SetLastError(ERROR_NO_UNICODE_TRANSLATION); + return 0; + } + } + } + + /* Does caller query for output buffer size? */ + if (WideCharCount == 0) + return MultiByteCount; + + /* Fill the WideCharString buffer with what will fit: Verified on WinXP */ + for (TempLength = (WideCharCount < MultiByteCount) ? WideCharCount : MultiByteCount; + TempLength > 0; + MultiByteString++, TempLength--) + { + *WideCharString++ = CodePageTable->MultiByteTable[(UCHAR)*MultiByteString]; + } + + /* Adjust buffer size. Wine trick ;-) */ + if (WideCharCount < MultiByteCount) + { + MultiByteCount = WideCharCount; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + return MultiByteCount; + } +} + +/** + * @name IntMultiByteToWideCharSYMBOL + * + * Internal version of MultiByteToWideChar for SYMBOL. + * + * @see MultiByteToWideChar + */ + +static +INT +WINAPI +IntMultiByteToWideCharSYMBOL(DWORD Flags, + LPCSTR MultiByteString, + INT MultiByteCount, + LPWSTR WideCharString, + INT WideCharCount) +{ + LONG Count; + UCHAR Char; + INT WideCharMaxLen; + + + if (Flags != 0) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + if (WideCharCount == 0) + { + return MultiByteCount; + } + + WideCharMaxLen = WideCharCount > MultiByteCount ? MultiByteCount : WideCharCount; + + for (Count = 0; Count < WideCharMaxLen; Count++) + { + Char = MultiByteString[Count]; + if ( Char < 0x20 ) + { + WideCharString[Count] = Char; + } + else + { + WideCharString[Count] = Char + 0xf000; + } + } + if (MultiByteCount > WideCharMaxLen) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + return WideCharMaxLen; +} + +/** + * @name IntWideCharToMultiByteSYMBOL + * + * Internal version of WideCharToMultiByte for SYMBOL. + * + * @see WideCharToMultiByte + */ + +static INT +WINAPI +IntWideCharToMultiByteSYMBOL(DWORD Flags, + LPCWSTR WideCharString, + INT WideCharCount, + LPSTR MultiByteString, + INT MultiByteCount) +{ + LONG Count; + INT MaxLen; + WCHAR Char; + + if (Flags!=0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + + if (MultiByteCount == 0) + { + return WideCharCount; + } + + MaxLen = MultiByteCount > WideCharCount ? WideCharCount : MultiByteCount; + for (Count = 0; Count < MaxLen; Count++) + { + Char = WideCharString[Count]; + if (Char < 0x20) + { + MultiByteString[Count] = Char; + } + else + { + if ((Char>=0xf020)&&(Char<0xf100)) + { + MultiByteString[Count] = Char - 0xf000; + } + else + { + SetLastError(ERROR_NO_UNICODE_TRANSLATION); + return 0; + } + } + } + if (WideCharCount > MaxLen) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + return MaxLen; +} + +/** + * @name IntWideCharToMultiByteUTF8 + * + * Internal version of WideCharToMultiByte for UTF8. + * + * @see WideCharToMultiByte + */ + +static INT +WINAPI +IntWideCharToMultiByteUTF8(UINT CodePage, + DWORD Flags, + LPCWSTR WideCharString, + INT WideCharCount, + LPSTR MultiByteString, + INT MultiByteCount, + LPCSTR DefaultChar, + LPBOOL UsedDefaultChar) +{ + INT TempLength; + WCHAR Char; + + /* Does caller query for output buffer size? */ + if (MultiByteCount == 0) + { + for (TempLength = 0; WideCharCount; + WideCharCount--, WideCharString++) + { + TempLength++; + if (*WideCharString >= 0x80) + { + TempLength++; + if (*WideCharString >= 0x800) + TempLength++; + } + } + return TempLength; + } + + for (TempLength = MultiByteCount; WideCharCount; WideCharCount--, WideCharString++) + { + Char = *WideCharString; + if (Char < 0x80) + { + if (!TempLength) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + break; + } + TempLength--; + *MultiByteString++ = (CHAR)Char; + continue; + } + + if (Char < 0x800) /* 0x80-0x7ff: 2 bytes */ + { + if (TempLength < 2) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + break; + } + MultiByteString[1] = 0x80 | (Char & 0x3f); Char >>= 6; + MultiByteString[0] = 0xc0 | Char; + MultiByteString += 2; + TempLength -= 2; + continue; + } + + /* 0x800-0xffff: 3 bytes */ + if (TempLength < 3) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + break; + } + MultiByteString[2] = 0x80 | (Char & 0x3f); Char >>= 6; + MultiByteString[1] = 0x80 | (Char & 0x3f); Char >>= 6; + MultiByteString[0] = 0xe0 | Char; + MultiByteString += 3; + TempLength -= 3; + } + + return MultiByteCount - TempLength; +} + +/** + * @name IsValidSBCSMapping + * + * Checks if ch (single-byte character) is a valid mapping for wch + * + * @see IntWideCharToMultiByteCP + */ +static +inline +BOOL +IntIsValidSBCSMapping(PCPTABLEINFO CodePageTable, DWORD Flags, WCHAR wch, UCHAR ch) +{ + /* If the WC_NO_BEST_FIT_CHARS flag has been specified, the characters need to match exactly. */ + if (Flags & WC_NO_BEST_FIT_CHARS) + return (CodePageTable->MultiByteTable[ch] == wch); + + /* By default, all characters except TransDefaultChar apply as a valid mapping + for ch (so also "nearest" characters) */ + if (ch != CodePageTable->TransDefaultChar) + return TRUE; + + /* The only possible left valid mapping is the default character itself */ + return (wch == CodePageTable->TransUniDefaultChar); +} + +/** + * @name IsValidDBCSMapping + * + * Checks if ch (double-byte character) is a valid mapping for wch + * + * @see IntWideCharToMultiByteCP + */ +static inline BOOL +IntIsValidDBCSMapping(PCPTABLEINFO CodePageTable, DWORD Flags, WCHAR wch, USHORT ch) +{ + /* If ch is the default character, but the wch is not, it can't be a valid mapping */ + if (ch == CodePageTable->TransDefaultChar && wch != CodePageTable->TransUniDefaultChar) + return FALSE; + + /* If the WC_NO_BEST_FIT_CHARS flag has been specified, the characters need to match exactly. */ + if (Flags & WC_NO_BEST_FIT_CHARS) + { + if(ch & 0xff00) + { + USHORT uOffset = CodePageTable->DBCSOffsets[ch >> 8]; + /* if (!uOffset) return (CodePageTable->MultiByteTable[ch] == wch); */ + return (CodePageTable->DBCSOffsets[uOffset + (ch & 0xff)] == wch); + } + + return (CodePageTable->MultiByteTable[ch] == wch); + } + + /* If we're still here, we have a valid mapping */ + return TRUE; +} + +/** + * @name IntWideCharToMultiByteCP + * + * Internal version of WideCharToMultiByte for code page tables. + * + * @see WideCharToMultiByte + * @todo Handle WC_COMPOSITECHECK + */ +static +INT +WINAPI +IntWideCharToMultiByteCP(UINT CodePage, + DWORD Flags, + LPCWSTR WideCharString, + INT WideCharCount, + LPSTR MultiByteString, + INT MultiByteCount, + LPCSTR DefaultChar, + LPBOOL UsedDefaultChar) +{ + PCODEPAGE_ENTRY CodePageEntry; + PCPTABLEINFO CodePageTable; + INT TempLength; + + /* Get code page table. */ + CodePageEntry = IntGetCodePageEntry(CodePage); + if (CodePageEntry == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + CodePageTable = &CodePageEntry->CodePageTable; + + + /* Different handling for DBCS code pages. */ + if (CodePageTable->MaximumCharacterSize > 1) + { + /* If Flags, DefaultChar or UsedDefaultChar were given, we have to do some more work */ + if(Flags || DefaultChar || UsedDefaultChar) + { + BOOL TempUsedDefaultChar; + USHORT DefChar; + + /* If UsedDefaultChar is not set, set it to a temporary value, so we don't have + to check on every character */ + if(!UsedDefaultChar) + UsedDefaultChar = &TempUsedDefaultChar; + + *UsedDefaultChar = FALSE; + + /* Use the CodePage's TransDefaultChar if none was given. Don't modify the DefaultChar pointer here. */ + if(DefaultChar) + DefChar = DefaultChar[1] ? ((DefaultChar[0] << 8) | DefaultChar[1]) : DefaultChar[0]; + else + DefChar = CodePageTable->TransDefaultChar; + + /* Does caller query for output buffer size? */ + if(!MultiByteCount) + { + for(TempLength = 0; WideCharCount; WideCharCount--, WideCharString++, TempLength++) + { + USHORT uChar; + + if ((Flags & WC_COMPOSITECHECK) && WideCharCount > 1) + { + /* FIXME: Handle WC_COMPOSITECHECK */ + } + + uChar = ((PUSHORT) CodePageTable->WideCharTable)[*WideCharString]; + + /* Verify if the mapping is valid for handling DefaultChar and UsedDefaultChar */ + if (!IntIsValidDBCSMapping(CodePageTable, Flags, *WideCharString, uChar)) + { + uChar = DefChar; + *UsedDefaultChar = TRUE; + } + + /* Increment TempLength again if this is a double-byte character */ + if (uChar & 0xff00) + TempLength++; + } + + return TempLength; + } + + /* Convert the WideCharString to the MultiByteString and verify if the mapping is valid */ + for(TempLength = MultiByteCount; + WideCharCount && TempLength; + TempLength--, WideCharString++, WideCharCount--) + { + USHORT uChar; + + if ((Flags & WC_COMPOSITECHECK) && WideCharCount > 1) + { + /* FIXME: Handle WC_COMPOSITECHECK */ + } + + uChar = ((PUSHORT)CodePageTable->WideCharTable)[*WideCharString]; + + /* Verify if the mapping is valid for handling DefaultChar and UsedDefaultChar */ + if (!IntIsValidDBCSMapping(CodePageTable, Flags, *WideCharString, uChar)) + { + uChar = DefChar; + *UsedDefaultChar = TRUE; + } + + /* Handle double-byte characters */ + if (uChar & 0xff00) + { + /* Don't output a partial character */ + if (TempLength == 1) + break; + + TempLength--; + *MultiByteString++ = uChar >> 8; + } + + *MultiByteString++ = (char)uChar; + } + + /* WideCharCount should be 0 if all characters were converted */ + if (WideCharCount) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + return MultiByteCount - TempLength; + } + + /* Does caller query for output buffer size? */ + if (!MultiByteCount) + { + for (TempLength = 0; WideCharCount; WideCharCount--, WideCharString++, TempLength++) + { + /* Increment TempLength again if this is a double-byte character */ + if (((PWCHAR)CodePageTable->WideCharTable)[*WideCharString] & 0xff00) + TempLength++; + } + + return TempLength; + } + + /* Convert the WideCharString to the MultiByteString */ + for (TempLength = MultiByteCount; + WideCharCount && TempLength; + TempLength--, WideCharString++, WideCharCount--) + { + USHORT uChar = ((PUSHORT) CodePageTable->WideCharTable)[*WideCharString]; + + /* Is this a double-byte character? */ + if (uChar & 0xff00) + { + /* Don't output a partial character */ + if (TempLength == 1) + break; + + TempLength--; + *MultiByteString++ = uChar >> 8; + } + + *MultiByteString++ = (char)uChar; + } + + /* WideCharCount should be 0 if all characters were converted */ + if (WideCharCount) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + return MultiByteCount - TempLength; + } + else /* Not DBCS code page */ + { + INT nReturn; + + /* If Flags, DefaultChar or UsedDefaultChar were given, we have to do some more work */ + if (Flags || DefaultChar || UsedDefaultChar) + { + BOOL TempUsedDefaultChar; + CHAR DefChar; + + /* If UsedDefaultChar is not set, set it to a temporary value, so we don't have + to check on every character */ + if (!UsedDefaultChar) + UsedDefaultChar = &TempUsedDefaultChar; + + *UsedDefaultChar = FALSE; + + /* Does caller query for output buffer size? */ + if (!MultiByteCount) + { + /* Loop through the whole WideCharString and check if we can get a valid mapping for each character */ + for (TempLength = 0; WideCharCount; TempLength++, WideCharString++, WideCharCount--) + { + if ((Flags & WC_COMPOSITECHECK) && WideCharCount > 1) + { + /* FIXME: Handle WC_COMPOSITECHECK */ + } + + if (!*UsedDefaultChar) + *UsedDefaultChar = !IntIsValidSBCSMapping(CodePageTable, + Flags, + *WideCharString, + ((PCHAR)CodePageTable->WideCharTable)[*WideCharString]); + } + + return TempLength; + } + + /* Use the CodePage's TransDefaultChar if none was given. Don't modify the DefaultChar pointer here. */ + if (DefaultChar) + DefChar = *DefaultChar; + else + DefChar = CodePageTable->TransDefaultChar; + + /* Convert the WideCharString to the MultiByteString and verify if the mapping is valid */ + for (TempLength = MultiByteCount; + WideCharCount && TempLength; + MultiByteString++, TempLength--, WideCharString++, WideCharCount--) + { + if ((Flags & WC_COMPOSITECHECK) && WideCharCount > 1) + { + /* FIXME: Handle WC_COMPOSITECHECK */ + } + + *MultiByteString = ((PCHAR)CodePageTable->WideCharTable)[*WideCharString]; + + if (!IntIsValidSBCSMapping(CodePageTable, Flags, *WideCharString, *MultiByteString)) + { + *MultiByteString = DefChar; + *UsedDefaultChar = TRUE; + } + } + + /* WideCharCount should be 0 if all characters were converted */ + if (WideCharCount) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + return MultiByteCount - TempLength; + } + + /* Does caller query for output buffer size? */ + if (!MultiByteCount) + return WideCharCount; + + /* Is the buffer large enough? */ + if (MultiByteCount < WideCharCount) + { + /* Convert the string up to MultiByteCount and return 0 */ + WideCharCount = MultiByteCount; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + nReturn = 0; + } + else + { + /* Otherwise WideCharCount will be the number of converted characters */ + nReturn = WideCharCount; + } + + /* Convert the WideCharString to the MultiByteString */ + for (TempLength = WideCharCount; --TempLength >= 0; WideCharString++, MultiByteString++) + { + *MultiByteString = ((PCHAR)CodePageTable->WideCharTable)[*WideCharString]; + } + + return nReturn; + } +} + +/** + * @name IntIsLeadByte + * + * Internal function to detect if byte is lead byte in specific character + * table. + */ + +static BOOL +WINAPI +IntIsLeadByte(PCPTABLEINFO TableInfo, BYTE Byte) +{ + UINT i; + + if (TableInfo->MaximumCharacterSize == 2) + { + for (i = 0; i < MAXIMUM_LEADBYTES && TableInfo->LeadByte[i]; i += 2) + { + if (Byte >= TableInfo->LeadByte[i] && Byte <= TableInfo->LeadByte[i+1]) + return TRUE; + } + } + + return FALSE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/** + * @name GetNlsSectionName + * + * Construct a name of NLS section. + * + * @param CodePage + * Code page number. + * @param Base + * Integer base used for converting to string. Usually set to 10. + * @param Unknown + * As the name suggests the meaning of this parameter is unknown. + * The native version of Kernel32 passes it as the third parameter + * to NlsConvertIntegerToString function, which is used for the + * actual conversion of the code page number. + * @param BaseName + * Base name of the section. (ex. "\\Nls\\NlsSectionCP") + * @param Result + * Buffer that will hold the constructed name. + * @param ResultSize + * Size of the buffer for the result. + * + * @return TRUE if the buffer was large enough and was filled with + * the requested information, FALSE otherwise. + * + * @implemented + */ + +BOOL +WINAPI +GetNlsSectionName(UINT CodePage, + UINT Base, + ULONG Unknown, + LPSTR BaseName, + LPSTR Result, + ULONG ResultSize) +{ + CHAR Integer[11]; + + if (!NT_SUCCESS(RtlIntegerToChar(CodePage, Base, sizeof(Integer), Integer))) + return FALSE; + + /* + * If the name including the terminating NULL character doesn't + * fit in the output buffer then fail. + */ + if (strlen(Integer) + strlen(BaseName) >= ResultSize) + return FALSE; + + lstrcpyA(Result, BaseName); + lstrcatA(Result, Integer); + + return TRUE; +} + +/** + * @name GetCPFileNameFromRegistry + * + * Get file name of code page definition file. + * + * @param CodePage + * Code page number to get file name of. + * @param FileName + * Buffer that is filled with file name of successful return. Can + * be set to NULL. + * @param FileNameSize + * Size of the buffer to hold file name in WCHARs. + * + * @return TRUE if the file name was retrieved, FALSE otherwise. + * + * @implemented + */ + +BOOL +WINAPI +GetCPFileNameFromRegistry(UINT CodePage, LPWSTR FileName, ULONG FileNameSize) +{ + WCHAR ValueNameBuffer[11]; + UNICODE_STRING KeyName, ValueName; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE KeyHandle; + PKEY_VALUE_PARTIAL_INFORMATION Kvpi; + DWORD KvpiSize; + BOOL bRetValue; + + bRetValue = FALSE; + + /* Convert the codepage number to string. */ + ValueName.Buffer = ValueNameBuffer; + ValueName.MaximumLength = sizeof(ValueNameBuffer); + + if (!NT_SUCCESS(RtlIntegerToUnicodeString(CodePage, 10, &ValueName))) + return bRetValue; + + /* Open the registry key containing file name mappings. */ + RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\" + L"CurrentControlSet\\Control\\Nls\\CodePage"); + InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, + NULL, NULL); + Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return bRetValue; + } + + /* Allocate buffer that will be used to query the value data. */ + KvpiSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + (MAX_PATH * sizeof(WCHAR)); + Kvpi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, KvpiSize); + if (Kvpi == NULL) + { + NtClose(KeyHandle); + return bRetValue; + } + + /* Query the file name for our code page. */ + Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, + Kvpi, KvpiSize, &KvpiSize); + + NtClose(KeyHandle); + + /* Check if we succeded and the value is non-empty string. */ + if (NT_SUCCESS(Status) && Kvpi->Type == REG_SZ && + Kvpi->DataLength > sizeof(WCHAR)) + { + bRetValue = TRUE; + if (FileName != NULL) + { + lstrcpynW(FileName, (WCHAR*)Kvpi->Data, + min(Kvpi->DataLength / sizeof(WCHAR), FileNameSize)); + } + } + + /* free temporary buffer */ + HeapFree(GetProcessHeap(),0,Kvpi); + return bRetValue; +} + +/** + * @name IsValidCodePage + * + * Detect if specified code page is valid and present in the system. + * + * @param CodePage + * Code page number to query. + * + * @return TRUE if code page is present. + */ + +BOOL +WINAPI +IsValidCodePage(UINT CodePage) +{ + if (CodePage == 0) return FALSE; + if (CodePage == CP_UTF8 || CodePage == CP_UTF7) + return TRUE; + if (IntGetLoadedCodePageEntry(CodePage)) + return TRUE; + return GetCPFileNameFromRegistry(CodePage, NULL, 0); +} + +static const signed char +base64inv[] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 +}; + +static VOID Utf7Base64Decode(BYTE *pbDest, LPCSTR pszSrc, INT cchSrc) +{ + INT i, j, n; + BYTE b; + + for(i = 0; i < cchSrc / 4 * 4; i += 4) + { + for(j = n = 0; j < 4; ) + { + b = (BYTE) base64inv[(BYTE) *pszSrc++]; + n |= (((INT) b) << ((3 - j) * 6)); + j++; + } + for(j = 0; j < 3; j++) + *pbDest++ = (BYTE) ((n >> (8 * (2 - j))) & 0xFF); + } + for(j = n = 0; j < cchSrc % 4; ) + { + b = (BYTE) base64inv[(BYTE) *pszSrc++]; + n |= (((INT) b) << ((3 - j) * 6)); + j++; + } + for(j = 0; j < ((cchSrc % 4) * 6 / 8); j++) + *pbDest++ = (BYTE) ((n >> (8 * (2 - j))) & 0xFF); +} + +static VOID myswab(LPVOID pv, INT cw) +{ + LPBYTE pb = (LPBYTE) pv; + BYTE b; + while(cw > 0) + { + b = *pb; + *pb = pb[1]; + pb[1] = b; + pb += 2; + cw--; + } +} + +static INT Utf7ToWideCharSize(LPCSTR pszUtf7, INT cchUtf7) +{ + INT n, c, cch; + CHAR ch; + LPCSTR pch; + + c = 0; + while(cchUtf7 > 0) + { + ch = *pszUtf7++; + if (ch == '+') + { + ch = *pszUtf7; + if (ch == '-') + { + c++; + pszUtf7++; + cchUtf7 -= 2; + continue; + } + cchUtf7--; + pch = pszUtf7; + while(cchUtf7 > 0 && (BYTE) *pszUtf7 < 0x80 && + base64inv[*pszUtf7] >= 0) + { + cchUtf7--; + pszUtf7++; + } + cch = pszUtf7 - pch; + n = (cch * 3) / 8; + c += n; + if (cchUtf7 > 0 && *pszUtf7 == '-') + { + pszUtf7++; + cchUtf7--; + } + } + else + { + c++; + cchUtf7--; + } + } + + return c; +} + +static INT Utf7ToWideChar(LPCSTR pszUtf7, INT cchUtf7, LPWSTR pszWide, INT cchWide) +{ + INT n, c, cch; + CHAR ch; + LPCSTR pch; + WORD *pwsz; + + c = Utf7ToWideCharSize(pszUtf7, cchUtf7); + if (cchWide == 0) + return c; + + if (cchWide < c) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + while(cchUtf7 > 0) + { + ch = *pszUtf7++; + if (ch == '+') + { + if (*pszUtf7 == '-') + { + *pszWide++ = L'+'; + pszUtf7++; + cchUtf7 -= 2; + continue; + } + cchUtf7--; + pch = pszUtf7; + while(cchUtf7 > 0 && (BYTE) *pszUtf7 < 0x80 && + base64inv[*pszUtf7] >= 0) + { + cchUtf7--; + pszUtf7++; + } + cch = pszUtf7 - pch; + n = (cch * 3) / 8; + pwsz = (WORD *) HeapAlloc(GetProcessHeap(), 0, (n + 1) * sizeof(WORD)); + if (pwsz == NULL) + return 0; + ZeroMemory(pwsz, n * sizeof(WORD)); + Utf7Base64Decode((BYTE *) pwsz, pch, cch); + myswab(pwsz, n); + CopyMemory(pszWide, pwsz, n * sizeof(WORD)); + HeapFree(GetProcessHeap(), 0, pwsz); + pszWide += n; + if (cchUtf7 > 0 && *pszUtf7 == '-') + { + pszUtf7++; + cchUtf7--; + } + } + else + { + *pszWide++ = (WCHAR) ch; + cchUtf7--; + } + } + + return c; +} + +/** + * @name MultiByteToWideChar + * + * Convert a multi-byte string to wide-charater equivalent. + * + * @param CodePage + * Code page to be used to perform the conversion. It can be also + * one of the special values (CP_ACP for ANSI code page, CP_MACCP + * for Macintosh code page, CP_OEMCP for OEM code page, CP_THREAD_ACP + * for thread active code page, CP_UTF7 or CP_UTF8). + * @param Flags + * Additional conversion flags (MB_PRECOMPOSED, MB_COMPOSITE, + * MB_ERR_INVALID_CHARS, MB_USEGLYPHCHARS). + * @param MultiByteString + * Input buffer. + * @param MultiByteCount + * Size of MultiByteString, or -1 if MultiByteString is NULL + * terminated. + * @param WideCharString + * Output buffer. + * @param WideCharCount + * Size in WCHARs of WideCharString, or 0 if the caller just wants + * to know how large WideCharString should be for a successful + * conversion. + * + * @return Zero on error, otherwise the number of WCHARs written + * in the WideCharString buffer. + * + * @implemented + */ + +INT +WINAPI +MultiByteToWideChar(UINT CodePage, + DWORD Flags, + LPCSTR MultiByteString, + INT MultiByteCount, + LPWSTR WideCharString, + INT WideCharCount) +{ + /* Check the parameters. */ + if (MultiByteString == NULL || + (WideCharString == NULL && WideCharCount > 0) || + (PVOID)MultiByteString == (PVOID)WideCharString) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + /* Determine the input string length. */ + if (MultiByteCount < 0) + { + MultiByteCount = lstrlenA(MultiByteString) + 1; + } + + switch (CodePage) + { + case CP_UTF8: + return IntMultiByteToWideCharUTF8(Flags, + MultiByteString, + MultiByteCount, + WideCharString, + WideCharCount); + + case CP_UTF7: + if (Flags) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + return Utf7ToWideChar(MultiByteString, MultiByteCount, + WideCharString, WideCharCount); + + case CP_SYMBOL: + return IntMultiByteToWideCharSYMBOL(Flags, + MultiByteString, + MultiByteCount, + WideCharString, + WideCharCount); + default: + return IntMultiByteToWideCharCP(CodePage, + Flags, + MultiByteString, + MultiByteCount, + WideCharString, + WideCharCount); + } +} + +static const char mustshift[] = +{ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 +}; + +static const char base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static INT WideCharToUtf7Size(LPCWSTR pszWide, INT cchWide) +{ + WCHAR wch; + INT c = 0; + BOOL fShift = FALSE; + + while(cchWide > 0) + { + wch = *pszWide; + if (wch < 0x80 && !mustshift[wch]) + { + c++; + cchWide--; + pszWide++; + } + else + { + if (wch == L'+') + { + c++; + c++; + cchWide--; + pszWide++; + continue; + } + if (!fShift) + { + c++; + fShift = TRUE; + } + pszWide++; + cchWide--; + c += 3; + if (cchWide > 0 && (*pszWide >= 0x80 || mustshift[*pszWide])) + { + pszWide++; + cchWide--; + c += 3; + if (cchWide > 0 && (*pszWide >= 0x80 || mustshift[*pszWide])) + { + pszWide++; + cchWide--; + c += 2; + } + } + if (cchWide > 0 && *pszWide < 0x80 && !mustshift[*pszWide]) + { + c++; + fShift = FALSE; + } + } + } + if (fShift) + c++; + + return c; +} + +static INT WideCharToUtf7(LPCWSTR pszWide, INT cchWide, LPSTR pszUtf7, INT cchUtf7) +{ + WCHAR wch; + INT c, n; + WCHAR wsz[3]; + BOOL fShift = FALSE; + + c = WideCharToUtf7Size(pszWide, cchWide); + if (cchUtf7 == 0) + return c; + + if (cchUtf7 < c) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + while(cchWide > 0) + { + wch = *pszWide; + if (wch < 0x80 && !mustshift[wch]) + { + *pszUtf7++ = (CHAR) wch; + cchWide--; + pszWide++; + } + else + { + if (wch == L'+') + { + *pszUtf7++ = '+'; + *pszUtf7++ = '-'; + cchWide--; + pszWide++; + continue; + } + if (!fShift) + { + *pszUtf7++ = '+'; + fShift = TRUE; + } + wsz[0] = *pszWide++; + cchWide--; + n = 1; + if (cchWide > 0 && (*pszWide >= 0x80 || mustshift[*pszWide])) + { + wsz[1] = *pszWide++; + cchWide--; + n++; + if (cchWide > 0 && (*pszWide >= 0x80 || mustshift[*pszWide])) + { + wsz[2] = *pszWide++; + cchWide--; + n++; + } + } + *pszUtf7++ = base64[wsz[0] >> 10]; + *pszUtf7++ = base64[(wsz[0] >> 4) & 0x3F]; + *pszUtf7++ = base64[(wsz[0] << 2 | wsz[1] >> 14) & 0x3F]; + if (n >= 2) + { + *pszUtf7++ = base64[(wsz[1] >> 8) & 0x3F]; + *pszUtf7++ = base64[(wsz[1] >> 2) & 0x3F]; + *pszUtf7++ = base64[(wsz[1] << 4 | wsz[2] >> 12) & 0x3F]; + if (n >= 3) + { + *pszUtf7++ = base64[(wsz[2] >> 6) & 0x3F]; + *pszUtf7++ = base64[wsz[2] & 0x3F]; + } + } + if (cchWide > 0 && *pszWide < 0x80 && !mustshift[*pszWide]) + { + *pszUtf7++ = '-'; + fShift = FALSE; + } + } + } + if (fShift) + *pszUtf7 = '-'; + + return c; +} + +static BOOL +GetLocalisedText(DWORD dwResId, WCHAR *lpszDest) +{ + HRSRC hrsrc; + LCID lcid; + LANGID langId; + DWORD dwId; + + if (dwResId == 37) + dwId = dwResId * 100; + else + dwId = dwResId; + + lcid = GetUserDefaultLCID(); + lcid = ConvertDefaultLocale(lcid); + + langId = LANGIDFROMLCID(lcid); + + if (PRIMARYLANGID(langId) == LANG_NEUTRAL) + langId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); + + hrsrc = FindResourceExW(hCurrentModule, + (LPWSTR)RT_STRING, + MAKEINTRESOURCEW((dwId >> 4) + 1), + langId); + if (hrsrc) + { + HGLOBAL hmem = LoadResource(hCurrentModule, hrsrc); + + if (hmem) + { + const WCHAR *p; + unsigned int i; + + p = LockResource(hmem); + for (i = 0; i < (dwId & 0x0f); i++) p += *p + 1; + + memcpy(lpszDest, p + 1, *p * sizeof(WCHAR)); + lpszDest[*p] = '\0'; + + return TRUE; + } + } + + DPRINT1("Could not get codepage name. dwResId = %ld\n", dwResId); + return FALSE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetCPInfo(UINT CodePage, + LPCPINFO CodePageInfo) +{ + PCODEPAGE_ENTRY CodePageEntry; + + if (!CodePageInfo) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + CodePageEntry = IntGetCodePageEntry(CodePage); + if (CodePageEntry == NULL) + { + switch(CodePage) + { + case CP_UTF7: + case CP_UTF8: + CodePageInfo->DefaultChar[0] = 0x3f; + CodePageInfo->DefaultChar[1] = 0; + CodePageInfo->LeadByte[0] = CodePageInfo->LeadByte[1] = 0; + CodePageInfo->MaxCharSize = (CodePage == CP_UTF7) ? 5 : 4; + return TRUE; + } + + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (CodePageEntry->CodePageTable.DefaultChar & 0xff00) + { + CodePageInfo->DefaultChar[0] = (CodePageEntry->CodePageTable.DefaultChar & 0xff00) >> 8; + CodePageInfo->DefaultChar[1] = CodePageEntry->CodePageTable.DefaultChar & 0x00ff; + } + else + { + CodePageInfo->DefaultChar[0] = CodePageEntry->CodePageTable.DefaultChar & 0xff; + CodePageInfo->DefaultChar[1] = 0; + } + + if ((CodePageInfo->MaxCharSize = CodePageEntry->CodePageTable.MaximumCharacterSize) == 2) + memcpy(CodePageInfo->LeadByte, CodePageEntry->CodePageTable.LeadByte, sizeof(CodePageInfo->LeadByte)); + else + CodePageInfo->LeadByte[0] = CodePageInfo->LeadByte[1] = 0; + + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetCPInfoExW(UINT CodePage, + DWORD dwFlags, + LPCPINFOEXW lpCPInfoEx) +{ + if (!GetCPInfo(CodePage, (LPCPINFO) lpCPInfoEx)) + return FALSE; + + switch(CodePage) + { + case CP_UTF7: + { + lpCPInfoEx->CodePage = CP_UTF7; + lpCPInfoEx->UnicodeDefaultChar = 0x3f; + return GetLocalisedText((DWORD)CodePage, lpCPInfoEx->CodePageName); + } + break; + + case CP_UTF8: + { + lpCPInfoEx->CodePage = CP_UTF8; + lpCPInfoEx->UnicodeDefaultChar = 0x3f; + return GetLocalisedText((DWORD)CodePage, lpCPInfoEx->CodePageName); + } + + default: + { + PCODEPAGE_ENTRY CodePageEntry; + + CodePageEntry = IntGetCodePageEntry(CodePage); + if (CodePageEntry == NULL) + { + DPRINT1("Could not get CodePage Entry! CodePageEntry = 0\n"); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + lpCPInfoEx->CodePage = CodePageEntry->CodePageTable.CodePage; + lpCPInfoEx->UnicodeDefaultChar = CodePageEntry->CodePageTable.UniDefaultChar; + return GetLocalisedText((DWORD)CodePage, lpCPInfoEx->CodePageName); + } + break; + } +} + + +/* + * @implemented + */ +BOOL +WINAPI +GetCPInfoExA(UINT CodePage, + DWORD dwFlags, + LPCPINFOEXA lpCPInfoEx) +{ + CPINFOEXW CPInfo; + + if (!GetCPInfoExW(CodePage, dwFlags, &CPInfo)) + return FALSE; + + /* the layout is the same except for CodePageName */ + memcpy(lpCPInfoEx, &CPInfo, sizeof(CPINFOEXA)); + + WideCharToMultiByte(CP_ACP, + 0, + CPInfo.CodePageName, + -1, + lpCPInfoEx->CodePageName, + sizeof(lpCPInfoEx->CodePageName), + NULL, + NULL); + return TRUE; +} + +/** + * @name WideCharToMultiByte + * + * Convert a wide-charater string to closest multi-byte equivalent. + * + * @param CodePage + * Code page to be used to perform the conversion. It can be also + * one of the special values (CP_ACP for ANSI code page, CP_MACCP + * for Macintosh code page, CP_OEMCP for OEM code page, CP_THREAD_ACP + * for thread active code page, CP_UTF7 or CP_UTF8). + * @param Flags + * Additional conversion flags (WC_NO_BEST_FIT_CHARS, WC_COMPOSITECHECK, + * WC_DISCARDNS, WC_SEPCHARS, WC_DEFAULTCHAR). + * @param WideCharString + * Points to the wide-character string to be converted. + * @param WideCharCount + * Size in WCHARs of WideCharStr, or 0 if the caller just wants to + * know how large WideCharString should be for a successful conversion. + * @param MultiByteString + * Points to the buffer to receive the translated string. + * @param MultiByteCount + * Specifies the size in bytes of the buffer pointed to by the + * MultiByteString parameter. If this value is zero, the function + * returns the number of bytes required for the buffer. + * @param DefaultChar + * Points to the character used if a wide character cannot be + * represented in the specified code page. If this parameter is + * NULL, a system default value is used. + * @param UsedDefaultChar + * Points to a flag that indicates whether a default character was + * used. This parameter can be NULL. + * + * @return Zero on error, otherwise the number of bytes written in the + * MultiByteString buffer. Or the number of bytes needed for + * the MultiByteString buffer if MultiByteCount is zero. + * + * @implemented + */ + +INT +WINAPI +WideCharToMultiByte(UINT CodePage, + DWORD Flags, + LPCWSTR WideCharString, + INT WideCharCount, + LPSTR MultiByteString, + INT MultiByteCount, + LPCSTR DefaultChar, + LPBOOL UsedDefaultChar) +{ + /* Check the parameters. */ + if (WideCharString == NULL || + (MultiByteString == NULL && MultiByteCount > 0) || + (PVOID)WideCharString == (PVOID)MultiByteString || + MultiByteCount < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + /* Determine the input string length. */ + if (WideCharCount < 0) + { + WideCharCount = lstrlenW(WideCharString) + 1; + } + + switch (CodePage) + { + case CP_UTF8: + return IntWideCharToMultiByteUTF8(CodePage, + Flags, + WideCharString, + WideCharCount, + MultiByteString, + MultiByteCount, + DefaultChar, + UsedDefaultChar); + + case CP_UTF7: + if (DefaultChar != NULL || UsedDefaultChar != NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (Flags) + { + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + return WideCharToUtf7(WideCharString, WideCharCount, + MultiByteString, MultiByteCount); + + case CP_SYMBOL: + if ((DefaultChar!=NULL) || (UsedDefaultChar!=NULL)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + return IntWideCharToMultiByteSYMBOL(Flags, + WideCharString, + WideCharCount, + MultiByteString, + MultiByteCount); + + default: + return IntWideCharToMultiByteCP(CodePage, + Flags, + WideCharString, + WideCharCount, + MultiByteString, + MultiByteCount, + DefaultChar, + UsedDefaultChar); + } +} + +/** + * @name GetACP + * + * Get active ANSI code page number. + * + * @implemented + */ + +UINT +WINAPI +GetACP(VOID) +{ + return AnsiCodePage.CodePageTable.CodePage; +} + +/** + * @name GetOEMCP + * + * Get active OEM code page number. + * + * @implemented + */ + +UINT +WINAPI +GetOEMCP(VOID) +{ + return OemCodePage.CodePageTable.CodePage; +} + +/** + * @name IsDBCSLeadByteEx + * + * Determine if passed byte is lead byte in specified code page. + * + * @implemented + */ + +BOOL +WINAPI +IsDBCSLeadByteEx(UINT CodePage, BYTE TestByte) +{ + PCODEPAGE_ENTRY CodePageEntry; + + CodePageEntry = IntGetCodePageEntry(CodePage); + if (CodePageEntry != NULL) + return IntIsLeadByte(&CodePageEntry->CodePageTable, TestByte); + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; +} + +/** + * @name IsDBCSLeadByteEx + * + * Determine if passed byte is lead byte in current ANSI code page. + * + * @implemented + */ + +BOOL +WINAPI +IsDBCSLeadByte(BYTE TestByte) +{ + return IntIsLeadByte(&AnsiCodePage.CodePageTable, TestByte); +} + +/* + * @unimplemented + */ +NTSTATUS WINAPI CreateNlsSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,ULONG Size,ULONG AccessMask) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL WINAPI IsValidUILanguage(LANGID langid) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +VOID WINAPI NlsConvertIntegerToString(ULONG Value,ULONG Base,ULONG strsize, LPWSTR str, ULONG strsize2) +{ + STUB; +} + +/* + * @unimplemented + */ +UINT WINAPI SetCPGlobal(UINT CodePage) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +ValidateLCType(int a1, unsigned int a2, int a3, int a4) +{ + STUB; + return FALSE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +NlsResetProcessLocale(VOID) +{ + STUB; + return TRUE; +} + +/* + * @unimplemented + */ +VOID +WINAPI +GetDefaultSortkeySize(LPVOID lpUnknown) +{ + STUB; + lpUnknown = NULL; +} + +/* + * @unimplemented + */ +VOID +WINAPI +GetLinguistLangSize(LPVOID lpUnknown) +{ + STUB; + lpUnknown = NULL; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +ValidateLocale(IN ULONG LocaleId) +{ + STUB; + return TRUE; +} + +/* + * @unimplemented + */ +ULONG +WINAPI +NlsGetCacheUpdateCount(VOID) +{ + STUB; + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +IsNLSDefinedString(IN NLS_FUNCTION Function, + IN DWORD dwFlags, + IN LPNLSVERSIONINFO lpVersionInformation, + IN LPCWSTR lpString, + IN INT cchStr) +{ + STUB; + return TRUE; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +GetNLSVersion(IN NLS_FUNCTION Function, + IN LCID Locale, + IN OUT LPNLSVERSIONINFO lpVersionInformation) +{ + STUB; + return TRUE; +} + +/* EOF */ diff --git a/dll/win32/kernel32/winnls/string/sortkey.c b/dll/win32/kernel32/winnls/string/sortkey.c new file mode 100644 index 00000000000..8f9bba5cd28 --- /dev/null +++ b/dll/win32/kernel32/winnls/string/sortkey.c @@ -0,0 +1,351 @@ +/* + * Unicode sort key generation + * + * Copyright 2003 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "wine/unicode.h" + +#define get_char_typeW(x) iswctype((x) >> 8, (x) & 0xFF) +extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen); +extern const unsigned int collation_table[]; + +/* + * flags - normalization NORM_* flags + * + * FIXME: 'variable' flag not handled + */ +int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen) +{ + WCHAR dummy[4]; /* no decomposition is larger than 4 chars */ + int key_len[4]; + char *key_ptr[4]; + const WCHAR *src_save = src; + int srclen_save = srclen; + + key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0; + for (; srclen; srclen--, src++) + { + int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/ + dummy[0] = *src; + if (decomposed_len) + { + int i; + for (i = 0; i < decomposed_len; i++) + { + WCHAR wch = dummy[i]; + unsigned int ce; + + /* tests show that win2k just ignores NORM_IGNORENONSPACE, + * and skips white space and punctuation characters for + * NORM_IGNORESYMBOLS. + */ + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + + if (flags & NORM_IGNORECASE) wch = tolowerW(wch); + + ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)]; + if (ce != (unsigned int)-1) + { + if (ce >> 16) key_len[0] += 2; + if ((ce >> 8) & 0xff) key_len[1]++; + if ((ce >> 4) & 0x0f) key_len[2]++; + if (ce & 1) + { + if (wch >> 8) key_len[3]++; + key_len[3]++; + } + } + else + { + key_len[0] += 2; + if (wch >> 8) key_len[0]++; + if (wch & 0xff) key_len[0]++; + } + } + } + } + + if (!dstlen) /* compute length */ + /* 4 * '\1' + 1 * '\0' + key length */ + return key_len[0] + key_len[1] + key_len[2] + key_len[3] + 4 + 1; + + if (dstlen < key_len[0] + key_len[1] + key_len[2] + key_len[3] + 4 + 1) + return 0; /* overflow */ + + src = src_save; + srclen = srclen_save; + + key_ptr[0] = dst; + key_ptr[1] = key_ptr[0] + key_len[0] + 1; + key_ptr[2] = key_ptr[1] + key_len[1] + 1; + key_ptr[3] = key_ptr[2] + key_len[2] + 1; + + for (; srclen; srclen--, src++) + { + int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/ + dummy[0] = *src; + if (decomposed_len) + { + int i; + for (i = 0; i < decomposed_len; i++) + { + WCHAR wch = dummy[i]; + unsigned int ce; + + /* tests show that win2k just ignores NORM_IGNORENONSPACE, + * and skips white space and punctuation characters for + * NORM_IGNORESYMBOLS. + */ + if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE))) + continue; + + if (flags & NORM_IGNORECASE) wch = tolowerW(wch); + + ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)]; + if (ce != (unsigned int)-1) + { + WCHAR key; + if ((key = ce >> 16)) + { + *key_ptr[0]++ = key >> 8; + *key_ptr[0]++ = key & 0xff; + } + /* make key 1 start from 2 */ + if ((key = (ce >> 8) & 0xff)) *key_ptr[1]++ = key + 1; + /* make key 2 start from 2 */ + if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1; + /* key 3 is always a character code */ + if (ce & 1) + { + if (wch >> 8) *key_ptr[3]++ = wch >> 8; + if (wch & 0xff) *key_ptr[3]++ = wch & 0xff; + } + } + else + { + *key_ptr[0]++ = 0xff; + *key_ptr[0]++ = 0xfe; + if (wch >> 8) *key_ptr[0]++ = wch >> 8; + if (wch & 0xff) *key_ptr[0]++ = wch & 0xff; + } + } + } + } + + *key_ptr[0] = '\1'; + *key_ptr[1] = '\1'; + *key_ptr[2] = '\1'; + *key_ptr[3]++ = '\1'; + *key_ptr[3] = 0; + + return key_ptr[3] - dst; +} + +static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1, + const WCHAR *str2, int len2) +{ + unsigned int ce1, ce2; + int ret; + + /* 32-bit collation element table format: + * unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit, + * case weight - high 4 bit of low 8 bit. + */ + while (len1 > 0 && len2 > 0) + { + if (flags & NORM_IGNORESYMBOLS) + { + int skip = 0; + /* FIXME: not tested */ + if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE)) + { + str1++; + len1--; + skip = 1; + } + if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE)) + { + str2++; + len2--; + skip = 1; + } + if (skip) continue; + } + + /* hyphen and apostrophe are treated differently depending on + * whether SORT_STRINGSORT specified or not + */ + if (!(flags & SORT_STRINGSORT)) + { + if (*str1 == '-' || *str1 == '\'') + { + if (*str2 != '-' && *str2 != '\'') + { + str1++; + len1--; + continue; + } + } + else if (*str2 == '-' || *str2 == '\'') + { + str2++; + len2--; + continue; + } + } + + ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)]; + ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)]; + + if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1) + ret = (ce1 >> 16) - (ce2 >> 16); + else + ret = *str1 - *str2; + + if (ret) return ret; + + str1++; + str2++; + len1--; + len2--; + } + return len1 - len2; +} + +static inline int compare_diacritic_weights(int flags, const WCHAR *str1, int len1, + const WCHAR *str2, int len2) +{ + unsigned int ce1, ce2; + int ret; + + /* 32-bit collation element table format: + * unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit, + * case weight - high 4 bit of low 8 bit. + */ + while (len1 > 0 && len2 > 0) + { + if (flags & NORM_IGNORESYMBOLS) + { + int skip = 0; + /* FIXME: not tested */ + if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE)) + { + str1++; + len1--; + skip = 1; + } + if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE)) + { + str2++; + len2--; + skip = 1; + } + if (skip) continue; + } + + ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)]; + ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)]; + + if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1) + ret = ((ce1 >> 8) & 0xff) - ((ce2 >> 8) & 0xff); + else + ret = *str1 - *str2; + + if (ret) return ret; + + str1++; + str2++; + len1--; + len2--; + } + return len1 - len2; +} + +static inline int compare_case_weights(int flags, const WCHAR *str1, int len1, + const WCHAR *str2, int len2) +{ + unsigned int ce1, ce2; + int ret; + + /* 32-bit collation element table format: + * unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit, + * case weight - high 4 bit of low 8 bit. + */ + while (len1 > 0 && len2 > 0) + { + if (flags & NORM_IGNORESYMBOLS) + { + int skip = 0; + /* FIXME: not tested */ + if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE)) + { + str1++; + len1--; + skip = 1; + } + if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE)) + { + str2++; + len2--; + skip = 1; + } + if (skip) continue; + } + + ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)]; + ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)]; + + if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1) + ret = ((ce1 >> 4) & 0x0f) - ((ce2 >> 4) & 0x0f); + else + ret = *str1 - *str2; + + if (ret) return ret; + + str1++; + str2++; + len1--; + len2--; + } + return len1 - len2; +} + +static inline int real_length(const WCHAR *str, int len) +{ + while (len && !str[len - 1]) len--; + return len; +} + +int wine_compare_string(int flags, const WCHAR *str1, int len1, + const WCHAR *str2, int len2) +{ + int ret; + + len1 = real_length(str1, len1); + len2 = real_length(str2, len2); + + ret = compare_unicode_weights(flags, str1, len1, str2, len2); + if (!ret) + { + if (!(flags & NORM_IGNORENONSPACE)) + ret = compare_diacritic_weights(flags, str1, len1, str2, len2); + if (!ret && !(flags & NORM_IGNORECASE)) + ret = compare_case_weights(flags, str1, len1, str2, len2); + } + return ret; +} diff --git a/dll/win32/msafd/misc/dllmain.c b/dll/win32/msafd/misc/dllmain.c index 4fa46d728c0..87e5dcd1511 100644 --- a/dll/win32/msafd/misc/dllmain.c +++ b/dll/win32/msafd/misc/dllmain.c @@ -1810,13 +1810,13 @@ WSPGetSockName(IN SOCKET Handle, if (NT_SUCCESS(Status)) { - if (*NameLength >= SocketAddress->Address[0].AddressLength) + if (*NameLength >= Socket->SharedData.SizeOfLocalAddress) { Name->sa_family = SocketAddress->Address[0].AddressType; RtlCopyMemory (Name->sa_data, SocketAddress->Address[0].Address, SocketAddress->Address[0].AddressLength); - *NameLength = 2 + SocketAddress->Address[0].AddressLength; + *NameLength = Socket->SharedData.SizeOfLocalAddress; AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %x Port %x\n", *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, ((struct sockaddr_in *)Name)->sin_port)); @@ -1882,7 +1882,7 @@ WSPGetPeerName(IN SOCKET s, } /* Allocate a buffer for the address */ - TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + *NameLength; + TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfRemoteAddress; SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); if ( SocketAddress == NULL ) @@ -1915,13 +1915,13 @@ WSPGetPeerName(IN SOCKET s, if (NT_SUCCESS(Status)) { - if (*NameLength >= SocketAddress->Address[0].AddressLength) + if (*NameLength >= Socket->SharedData.SizeOfRemoteAddress) { Name->sa_family = SocketAddress->Address[0].AddressType; RtlCopyMemory (Name->sa_data, SocketAddress->Address[0].Address, SocketAddress->Address[0].AddressLength); - *NameLength = 2 + SocketAddress->Address[0].AddressLength; + *NameLength = Socket->SharedData.SizeOfRemoteAddress; AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %s Port %x\n", *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, ((struct sockaddr_in *)Name)->sin_port)); diff --git a/dll/win32/msi/CMakeLists.txt b/dll/win32/msi/CMakeLists.txt index ecd80871870..b52c905dcb5 100644 --- a/dll/win32/msi/CMakeLists.txt +++ b/dll/win32/msi/CMakeLists.txt @@ -68,6 +68,7 @@ if(MSVC) endif() add_library(msi SHARED ${SOURCE}) +add_pch(msi msipriv.h) add_idl_Headers(msi_idlheader msiserver.idl) add_typelib(msi_tlb msiserver.idl) diff --git a/dll/win32/msvcrt/CMakeLists.txt b/dll/win32/msvcrt/CMakeLists.txt index 6e614730c78..20af9d7a2bf 100644 --- a/dll/win32/msvcrt/CMakeLists.txt +++ b/dll/win32/msvcrt/CMakeLists.txt @@ -33,8 +33,11 @@ set_image_base(msvcrt ${baseaddress_msvcrt}) target_link_libraries(msvcrt crt - wine - ${PSEH_LIB}) + wine) + +if(NOT MSVC) + target_link_libraries(msvcrt pseh) +endif() add_pch(msvcrt precomp.h) add_importlibs(msvcrt kernel32 ntdll) diff --git a/dll/win32/msvcrt/msvcrt.spec b/dll/win32/msvcrt/msvcrt.spec index b55f7aac52f..02d506e9699 100644 --- a/dll/win32/msvcrt/msvcrt.spec +++ b/dll/win32/msvcrt/msvcrt.spec @@ -104,7 +104,7 @@ @ cdecl _Getdays() @ cdecl _Getmonths() @ cdecl _Gettnames() -@ extern _HUGE _HUGE +@ extern _HUGE @ cdecl _Strftime(str long str ptr ptr) @ cdecl _XcptFilter(long ptr) @ cdecl __CppXcptFilter(long ptr) @@ -132,8 +132,8 @@ # @ cdecl ___mb_cur_max_func() MSVCRT___mb_cur_max_func @ cdecl ___setlc_active_func() @ cdecl ___unguarded_readlc_active_add_func() -@ extern __argc __argc -@ extern __argv __argv +@ extern __argc +@ extern __argv @ extern __badioinfo __badioinfo @ cdecl __crtCompareStringA(long long str long str long) kernel32.CompareStringA @ cdecl __crtCompareStringW(long long wstr long wstr long) kernel32.CompareStringW @@ -142,15 +142,15 @@ @ cdecl __crtLCMapStringA(long long str long ptr long long long) # stub __crtLCMapStringW @ cdecl __dllonexit(ptr ptr ptr) -@ cdecl __doserrno() __doserrno +@ cdecl __doserrno() @ cdecl __fpecode() @ cdecl __get_app_type() @ cdecl __getmainargs(ptr ptr ptr long ptr) -@ extern __initenv __initenv +@ extern __initenv @ cdecl __iob_func() __p__iob -@ cdecl __isascii(long) __isascii -@ cdecl __iscsym(long) __iscsym -@ cdecl __iscsymf(long) __iscsymf +@ cdecl __isascii(long) +@ cdecl __iscsym(long) +@ cdecl __iscsymf(long) @ extern __lc_codepage MSVCRT___lc_codepage # @ stub __lc_collate # not in XP / 7 @ extern __lc_collate_cp MSVCRT___lc_collate_cp @@ -177,7 +177,7 @@ # stub __libm_sse2_sinf # stub __libm_sse2_tan # stub __libm_sse2_tanf -@ extern __mb_cur_max __mb_cur_max +@ extern __mb_cur_max @ cdecl -arch=i386 __p___argc() @ cdecl -arch=i386 __p___argv() @ cdecl -arch=i386 __p___initenv() @@ -196,10 +196,10 @@ @ cdecl -arch=i386 __p__mbcasemap() @ cdecl -arch=i386 __p__mbctype() @ cdecl -arch=i386 __p__osver() -@ cdecl -arch=i386 __p__pctype() __pctype_func +@ cdecl -arch=i386 __p__pctype() @ cdecl -arch=i386 __p__pgmptr() @ cdecl -arch=i386 __p__pwctype() -@ cdecl -arch=i386 __p__timezone() __p__timezone +@ cdecl -arch=i386 __p__timezone() @ cdecl -arch=i386 __p__tzname() @ cdecl -arch=i386 __p__wcmdln() @ cdecl -arch=i386 __p__wenviron() @@ -207,9 +207,9 @@ @ cdecl -arch=i386 __p__winminor() @ cdecl -arch=i386 __p__winver() @ cdecl -arch=i386 __p__wpgmptr() -@ cdecl __pctype_func() __pctype_func -@ extern __pioinfo __pioinfo -# stub __pwctype_func +@ cdecl __pctype_func() +@ extern __pioinfo +@ cdecl __pwctype_func() @ cdecl __pxcptinfoptrs() @ cdecl __set_app_type(long) @ extern __setlc_active @@ -232,7 +232,7 @@ # stub _abs64 @ cdecl _access(str long) # stub _access_s -@ extern _acmdln _acmdln +@ extern _acmdln @ stdcall -arch=i386 _adj_fdiv_m16i(long) @ stdcall -arch=i386 _adj_fdiv_m32(long) @ stdcall -arch=i386 _adj_fdiv_m32i(long) @@ -247,7 +247,7 @@ @ cdecl -arch=i386 _adj_fprem1() @ cdecl -arch=i386 _adj_fptan() @ extern -arch=i386 _adjust_fdiv -# extern _aexit_rtn +@ extern _aexit_rtn @ cdecl _aligned_free(ptr) # stub _aligned_free_dbg @ cdecl _aligned_malloc(long long) @@ -271,8 +271,8 @@ @ cdecl _atoldbl(ptr str) # stub _atoldbl_l @ cdecl _beep(long long) -@ cdecl _beginthread (ptr long ptr) -@ cdecl _beginthreadex (ptr long ptr ptr long ptr) +@ cdecl _beginthread(ptr long ptr) +@ cdecl _beginthreadex(ptr long ptr ptr long ptr) @ cdecl _c_exit() @ cdecl _cabs(long) @ cdecl _callnewh(long) @@ -335,11 +335,11 @@ @ cdecl _difftime32(long long) @ cdecl _difftime64(long long) @ extern _dstbias -@ cdecl _dup (long) -@ cdecl _dup2 (long long) +@ cdecl _dup(long) +@ cdecl _dup2(long long) @ cdecl _ecvt(double long ptr ptr) # stub _ecvt_s -@ cdecl _endthread () +@ cdecl _endthread() @ cdecl _endthreadex(long) @ extern _environ @ cdecl _eof(long) @@ -355,7 +355,7 @@ @ cdecl _execve(str ptr ptr) @ cdecl _execvp(str ptr) @ cdecl _execvpe(str ptr ptr) -@ cdecl _exit(long) _exit +@ cdecl _exit(long) @ cdecl _expand(ptr long) # stub _expand_dbg @ cdecl _fcloseall() @@ -462,11 +462,11 @@ # stub _gmtime32_s @ cdecl _gmtime64(ptr) # stub _gmtime64_s -@ cdecl _heapadd (ptr long) +@ cdecl _heapadd(ptr long) @ cdecl _heapchk() @ cdecl _heapmin() @ cdecl _heapset(long) -# @ stub _heapused #(ptr ptr) # not in XP / 7 +@ cdecl _heapused(ptr ptr) @ cdecl _heapwalk(ptr) @ cdecl _hypot(double double) @ cdecl _i64toa(long long ptr long) @@ -492,7 +492,7 @@ # stub _islower_l @ cdecl _ismbbalnum(long) # stub _ismbbalnum_l -@ stub _ismbbalpha #(long) +@ cdecl _ismbbalpha(long) # stub _ismbbalpha_l @ cdecl _ismbbgraph(long) # stub _ismbbgraph_l @@ -506,7 +506,7 @@ # stub _ismbbkpunct_l @ cdecl _ismbblead(long) # stub _ismbblead_l -@ stub _ismbbprint #(long) +@ cdecl _ismbbprint(long) # stub _ismbbprint_l @ cdecl _ismbbpunct(long) # stub _ismbbpunct_l @@ -569,9 +569,9 @@ # stub _itoa_s @ cdecl _itow(long ptr long) # stub _itow_s -#@ cdecl _j0(double) -#@ cdecl _j1(double) -#@ cdecl _jn(long double) +@ cdecl _j0(double) +@ cdecl _j1(double) +@ cdecl _jn(long double) @ cdecl _kbhit() @ cdecl _lfind(ptr ptr ptr long ptr) # stub _lfind_s @@ -584,7 +584,7 @@ # stub _localtime64_s @ cdecl _lock(long) @ cdecl _locking(long long long) -@ cdecl _logb( double ) +@ cdecl _logb(double) @ cdecl -i386 _longjmpex(ptr long) longjmp @ cdecl _lrotl(long long) @ cdecl _lrotr(long long) @@ -607,7 +607,7 @@ # stub _mbccpy_l # stub _mbccpy_s # stub _mbccpy_s_l -@ cdecl _mbcjistojms (long) +@ cdecl _mbcjistojms(long) # stub _mbcjistojms_l @ cdecl _mbcjmstojis(long) # stub _mbcjmstojis_l @@ -639,11 +639,11 @@ @ cdecl _mbscpy(ptr str) # stub _mbscpy_s # stub _mbscpy_s_l -@ cdecl _mbscspn (str str) +@ cdecl _mbscspn(str str) # stub _mbscspn_l @ cdecl _mbsdec(ptr ptr) # stub _mbsdec_l -@ cdecl _mbsdup(str) _strdup +@ cdecl _mbsdup(str) # stub _strdup_dbg @ cdecl _mbsicmp(str str) # stub _mbsicmp_l @@ -657,7 +657,7 @@ # stub _mbslwr_l # stub _mbslwr_s # stub _mbslwr_s_l -@ cdecl _mbsnbcat (str str long) +@ cdecl _mbsnbcat(str str long) # stub _mbsnbcat_l # stub _mbsnbcat_s # stub _mbsnbcat_s_l @@ -755,16 +755,16 @@ @ cdecl _onexit(ptr) @ varargs _open(str long) @ cdecl _open_osfhandle(long long) -@ extern _osplatform _osplatform -@ extern _osver _osver +@ extern _osplatform +@ extern _osver @ cdecl _outp(long long) MSVCRT__outp @ cdecl _outpd(long long) MSVCRT__outpd @ cdecl _outpw(long long) MSVCRT__outpw -@ cdecl _pclose (ptr) -@ extern _pctype _pctype -@ extern _pgmptr _pgmptr -@ cdecl _pipe (ptr long long) -@ cdecl _popen (str str) +@ cdecl _pclose(ptr) +@ extern _pctype +@ extern _pgmptr +@ cdecl _pipe(ptr long long) +@ cdecl _popen(str str) # stub _printf_l # stub _printf_p # stub _printf_p_l @@ -813,7 +813,7 @@ # stub _set_output_format @ cdecl _set_sbh_threshold(long) @ cdecl _seterrormode(long) -@ cdecl -arch=i386,x86_64 -norelay _setjmp(ptr ptr) +@ cdecl -arch=i386,x86_64 -norelay _setjmp(ptr) @ cdecl -arch=i386 -norelay _setjmp3(ptr long) @ cdecl -arch=x86_64 -norelay _setjmpex(ptr ptr) @ cdecl _setmaxstdio(long) @@ -1005,7 +1005,7 @@ # stub _wassert @ cdecl _wchdir(wstr) @ cdecl _wchmod(wstr long) -@ extern _wcmdln _wcmdln +@ extern _wcmdln @ cdecl _wcreat(wstr long) # stub _wcscoll_l @ cdecl _wcsdup(wstr) @@ -1084,7 +1084,7 @@ @ extern _winminor # stub _winput_s @ extern _winver -@ cdecl _wmakepath(wstr wstr wstr wstr wstr) +@ cdecl _wmakepath(ptr wstr wstr wstr wstr) @ cdecl _wmakepath_s(ptr long wstr wstr wstr wstr) @ cdecl _wmkdir(wstr) @ cdecl _wmktemp(wstr) @@ -1093,7 +1093,7 @@ # stub _woutput_s @ cdecl _wperror(wstr) @ extern _wpgmptr -@ cdecl _wpopen (wstr wstr) +@ cdecl _wpopen(wstr wstr) # stub _wprintf_l # stub _wprintf_p # stub _wprintf_p_l @@ -1109,7 +1109,7 @@ @ cdecl _wsearchenv(wstr wstr ptr) # stub _wsearchenv_s @ cdecl _wsetlocale(long wstr) -@ varargs _wsopen (wstr long long) +@ varargs _wsopen(wstr long long) # stub _wsopen_s @ varargs _wspawnl(long wstr wstr) @ varargs _wspawnle(long wstr wstr) @@ -1145,9 +1145,9 @@ @ cdecl _wutime(wstr ptr) @ cdecl _wutime32(wstr ptr) @ cdecl _wutime64(wstr ptr) -#@ cdecl _y0(double) -#@ cdecl _y1(double) -#@ cdecl _yn(long double ) +@ cdecl _y0(double) +@ cdecl _y1(double) +@ cdecl _yn(long double ) @ cdecl abort() @ cdecl abs(long) @ cdecl acos(double) @@ -1156,7 +1156,7 @@ @ cdecl asin(double) @ cdecl atan(double) @ cdecl atan2(double double) -@ extern atexit # mingw hack +@ extern atexit # <-- keep this as an extern, thank you @ cdecl atof(str) @ cdecl atoi(str) @ cdecl atol(str) @@ -1220,7 +1220,7 @@ @ cdecl getwc(ptr) @ cdecl getwchar() @ cdecl gmtime(ptr) -@ cdecl is_wctype(long long)iswctype +@ cdecl is_wctype(long long) @ cdecl isalnum(long) @ cdecl isalpha(long) @ cdecl iscntrl(long) diff --git a/dll/win32/msvcrt/stubs.c b/dll/win32/msvcrt/stubs.c index 539a31652ce..e6b26752ef4 100644 --- a/dll/win32/msvcrt/stubs.c +++ b/dll/win32/msvcrt/stubs.c @@ -10,7 +10,7 @@ int __get_app_type() return 0; } -int _fileinfo; +int _fileinfo = 0; void * __p__fileinfo() @@ -41,6 +41,11 @@ int _ismbbkprint( return 0; } +size_t _heapused( size_t *pUsed, size_t *pCommit ) +{ + UNIMPLEMENTED; + return( 0 ); +} int MSVCRT__inp( unsigned short port) diff --git a/dll/win32/msvcrt20/CMakeLists.txt b/dll/win32/msvcrt20/CMakeLists.txt index fb3bc51dd93..db4d235d7df 100644 --- a/dll/win32/msvcrt20/CMakeLists.txt +++ b/dll/win32/msvcrt20/CMakeLists.txt @@ -1,20 +1,34 @@ -include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) +add_definitions( + -DUSE_MSVCRT_PREFIX + -D_MSVCRT_ + -D_MSVCRT_LIB_ + -D_MT + -D_CTYPE_DISABLE_MACROS + -D_NO_INLINING + -DCRTDLL + -D__MINGW_IMPORT="") -add_definitions(-D__WINESRC__) -add_definitions(-DCRTDLL) +include_directories(${REACTOS_SOURCE_DIR}/lib/sdk/crt/include) spec2def(msvcrt20.dll msvcrt20.spec) list(APPEND SOURCE msvcrt20.c + stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/msvcrt20_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/msvcrt20.def) add_library(msvcrt20 SHARED ${SOURCE}) -set_entrypoint(msvcrt20 0) +set_entrypoint(msvcrt20 DllMain@12) +set_image_base(msvcrt20 ${baseaddress_msvcrt20}) -target_link_libraries(msvcrt20 wine) +target_link_libraries(msvcrt20 crt wine) -add_importlibs(msvcrt20 msvcrt kernel32 ntdll) +if(NOT MSVC) + target_link_libraries(msvcrt20 pseh) +endif() + +add_importlibs(msvcrt20 kernel32 ntdll) add_dependencies(msvcrt20 psdk) add_cd_file(TARGET msvcrt20 DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/msvcrt20/msvcrt20.c b/dll/win32/msvcrt20/msvcrt20.c index e8d2b3cd378..23875143e09 100644 --- a/dll/win32/msvcrt20/msvcrt20.c +++ b/dll/win32/msvcrt20/msvcrt20.c @@ -18,15 +18,143 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include +#define _CRT_PRECOMP_H +#include +#include +#include +#include +#include +#include -#include "windef.h" +#include "wine/debug.h" +WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); + +/* EXTERNAL PROTOTYPES ********************************************************/ + +extern int BlockEnvToEnvironA(void); +extern int BlockEnvToEnvironW(void); +extern void FreeEnvironment(char **environment); +extern void _atexit_cleanup(void); + +extern unsigned int _osplatform; +extern unsigned int _osver; +extern unsigned int _winminor; +extern unsigned int _winmajor; +extern unsigned int _winver; + +extern char* _acmdln; /* pointer to ascii command line */ +extern wchar_t* _wcmdln; /* pointer to wide character command line */ +#undef _environ +extern char** _environ; /* pointer to environment block */ +extern char** __initenv; /* pointer to initial environment block */ +extern wchar_t** _wenviron; /* pointer to environment block */ +extern wchar_t** __winitenv; /* pointer to initial environment block */ extern void CDECL __getmainargs(int *argc, char** *argv, char** *envp, int expand_wildcards, int *new_mode); extern void CDECL __wgetmainargs(int *argc, WCHAR** *wargv, WCHAR** *wenvp, int expand_wildcards, int *new_mode); +/* LIBRARY GLOBAL VARIABLES ***************************************************/ + +HANDLE hHeap = NULL; /* handle for heap */ + + +/* LIBRARY ENTRY POINT ********************************************************/ + +BOOL +WINAPI +DllMain(PVOID hinstDll, ULONG dwReason, PVOID reserved) +{ + OSVERSIONINFOW osvi; + switch (dwReason) + { + case DLL_PROCESS_ATTACH://1 + /* initialize version info */ + //DPRINT1("Process Attach %d\n", nAttachCount); + //DPRINT1("Process Attach\n"); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + GetVersionExW( &osvi ); + _winver = (osvi.dwMajorVersion << 8) | osvi.dwMinorVersion; + _winmajor = osvi.dwMajorVersion; + _winminor = osvi.dwMinorVersion; + _osplatform = osvi.dwPlatformId; + _osver = osvi.dwBuildNumber; + hHeap = HeapCreate(0, 100000, 0); + if (hHeap == NULL) + return FALSE; + + /* create tls stuff */ + if (!CreateThreadData()) + return FALSE; + + if (BlockEnvToEnvironA() < 0) + return FALSE; + + if (BlockEnvToEnvironW() < 0) + { + FreeEnvironment(_environ); + return FALSE; + } + + _acmdln = _strdup(GetCommandLineA()); + _wcmdln = _wcsdup(GetCommandLineW()); + + /* FIXME: more initializations... */ + + /* Initialization of the WINE code */ + msvcrt_init_mt_locks(); + msvcrt_init_io(); + setlocale(0, "C"); + //_setmbcp(_MB_CP_LOCALE); + + TRACE("Attach done\n"); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + FreeThreadData(NULL); + break; + + case DLL_PROCESS_DETACH: + //DPRINT1("Detach %d\n", nAttachCount); + //DPRINT("Detach\n"); + /* FIXME: more cleanup... */ + /* Deinit of the WINE code */ + msvcrt_free_io(); + msvcrt_free_mt_locks(); + + _atexit_cleanup(); + + + /* destroy tls stuff */ + DestroyThreadData(); + + if (__winitenv && __winitenv != _wenviron) + FreeEnvironment((char**)__winitenv); + if (_wenviron) + FreeEnvironment((char**)_wenviron); + + if (__initenv && __initenv != _environ) + FreeEnvironment(__initenv); + if (_environ) + FreeEnvironment(_environ); + + /* destroy heap */ + HeapDestroy(hHeap); + + TRACE("Detach done\n"); + break; + } + + return TRUE; +} + +/* LIBRARY EXPORTS ************************************************************/ + /********************************************************************* * __getmainargs (MSVCRT20.@) * @@ -48,3 +176,5 @@ void CDECL MSVCRT20__wgetmainargs( int *argc, WCHAR** *wargv, WCHAR** *wenvp, { __wgetmainargs( argc, wargv, wenvp, expand_wildcards, &new_mode ); } + +/* EOF */ \ No newline at end of file diff --git a/dll/win32/msvcrt20/msvcrt20.spec b/dll/win32/msvcrt20/msvcrt20.spec index dffade1ec24..3a6a103a065 100644 --- a/dll/win32/msvcrt20/msvcrt20.spec +++ b/dll/win32/msvcrt20/msvcrt20.spec @@ -77,8 +77,8 @@ @ stub ??1streambuf@@UAE@XZ # @ stub ??1strstream@@UAE@XZ # @ stub ??1strstreambuf@@UAE@XZ # -@ cdecl ??2@YAPAXI@Z(long) msvcrt.??2@YAPAXI@Z -@ cdecl ??3@YAXPAX@Z(ptr) msvcrt.??3@YAXPAX@Z +@ cdecl ??2@YAPAXI@Z(long) MSVCRT_operator_new +@ cdecl ??3@YAXPAX@Z(ptr) MSVCRT_operator_delete @ stub ??4Iostream_init@@QAEAAV0@ABV0@@Z # @ stub ??4filebuf@@QAEAAV0@ABV0@@Z # @ stub ??4fstream@@QAEAAV0@AAV0@@Z # @@ -224,11 +224,11 @@ @ stub ??_Gstreambuf@@UAEPAXI@Z # @ stub ??_Gstrstream@@UAEPAXI@Z # @ stub ??_Gstrstreambuf@@UAEPAXI@Z # -@ cdecl ?_query_new_handler@@YAP6AHI@ZXZ() msvcrt.?_query_new_handler@@YAP6AHI@ZXZ -@ cdecl ?_query_new_mode@@YAHXZ() msvcrt.?_query_new_mode@@YAHXZ -@ cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) msvcrt.?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z -@ cdecl ?_set_new_mode@@YAHH@Z(long) msvcrt.?_set_new_mode@@YAHH@Z -@ cdecl ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z +@ cdecl ?_query_new_handler@@YAP6AHI@ZXZ() MSVCRT__query_new_handler +@ cdecl ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode +@ cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) MSVCRT__set_new_handler +@ cdecl ?_set_new_mode@@YAHH@Z(long) MSVCRT__set_new_mode +@ cdecl ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) MSVCRT__set_se_translator @ stub ?adjustfield@ios@@2JB # @ stub ?allocate@streambuf@@IAEHXZ # @ stub ?attach@filebuf@@QAEPAV1@H@Z # @@ -363,8 +363,8 @@ @ stub ?seekp@ostream@@QAEAAV1@J@Z # @ stub ?seekp@ostream@@QAEAAV1@JW4seek_dir@ios@@@Z # @ stub ?seekpos@streambuf@@UAEJJH@Z # -@ cdecl ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) msvcrt.?set_terminate@@YAP6AXXZP6AXXZ@Z -@ cdecl ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) msvcrt.?set_unexpected@@YAP6AXXZP6AXXZ@Z +@ cdecl ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_terminate +@ cdecl ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_unexpected @ stub ?setb@streambuf@@IAEXPAD0H@Z # @ stub ?setbuf@filebuf@@UAEPAVstreambuf@@PADH@Z # @ stub ?setbuf@fstream@@QAEPAVstreambuf@@PADH@Z # @@ -407,7 +407,7 @@ @ stub ?sync_with_stdio@ios@@SAXXZ # @ stub ?tellg@istream@@QAEJXZ # @ stub ?tellp@ostream@@QAEJXZ # -@ cdecl ?terminate@@YAXXZ() msvcrt.?terminate@@YAXXZ +@ cdecl ?terminate@@YAXXZ() MSVCRT_terminate @ stub ?text@filebuf@@2HB # @ stub ?tie@ios@@QAEPAVostream@@PAV2@@Z # @ stub ?tie@ios@@QBEPAVostream@@XZ # @@ -416,7 +416,7 @@ @ stub ?underflow@filebuf@@UAEHXZ # @ stub ?underflow@stdiobuf@@UAEHXZ # @ stub ?underflow@strstreambuf@@UAEHXZ # -@ cdecl ?unexpected@@YAXXZ() msvcrt.?unexpected@@YAXXZ +@ cdecl ?unexpected@@YAXXZ() MSVCRT_unexpected @ stub ?unlock@ios@@QAAXXZ # @ stub ?unlock@streambuf@@QAEXXZ # @ stub ?unlockbuf@ios@@QAAXXZ # @@ -436,692 +436,692 @@ @ stub ?xalloc@ios@@SAHXZ # @ stub ?xsgetn@streambuf@@UAEHPADH@Z # @ stub ?xsputn@streambuf@@UAEHPBDH@Z # -@ cdecl $I10_OUTPUT() msvcrt.$I10_OUTPUT -@ cdecl -arch=i386 _CIacos() msvcrt._CIacos -@ cdecl -arch=i386 _CIasin() msvcrt._CIasin -@ cdecl -arch=i386 _CIatan() msvcrt._CIatan -@ cdecl -arch=i386 _CIatan2() msvcrt._CIatan2 -@ cdecl -arch=i386 _CIcos() msvcrt._CIcos -@ cdecl -arch=i386 _CIcosh() msvcrt._CIcosh -@ cdecl -arch=i386 _CIexp() msvcrt._CIexp -@ cdecl -arch=i386 _CIfmod() msvcrt._CIfmod -@ cdecl -arch=i386 _CIlog() msvcrt._CIlog -@ cdecl -arch=i386 _CIlog10() msvcrt._CIlog10 -@ cdecl -arch=i386 _CIpow() msvcrt._CIpow -@ cdecl -arch=i386 _CIsin() msvcrt._CIsin -@ cdecl -arch=i386 _CIsinh() msvcrt._CIsinh -@ cdecl -arch=i386 _CIsqrt() msvcrt._CIsqrt -@ cdecl -arch=i386 _CItan() msvcrt._CItan -@ cdecl -arch=i386 _CItanh() msvcrt._CItanh -@ stdcall _CxxThrowException(long long) msvcrt._CxxThrowException -@ extern _HUGE msvcrt._HUGE -@ cdecl _XcptFilter(long ptr) msvcrt._XcptFilter -@ cdecl -i386 __CxxFrameHandler(ptr ptr ptr ptr) msvcrt.__CxxFrameHandler -@ stdcall __CxxLongjmpUnwind(ptr) msvcrt.__CxxLongjmpUnwind -@ cdecl __STRINGTOLD(ptr ptr str long) msvcrt.__STRINGTOLD -@ extern __argc msvcrt.__argc -@ extern __argv msvcrt.__argv -@ cdecl __dllonexit(ptr ptr ptr) msvcrt.__dllonexit -@ cdecl __doserrno() msvcrt.__doserrno -@ cdecl __fpecode() msvcrt.__fpecode +@ cdecl $I10_OUTPUT() MSVCRT_I10_OUTPUT +@ cdecl -arch=i386 _CIacos() +@ cdecl -arch=i386 _CIasin() +@ cdecl -arch=i386 _CIatan() +@ cdecl -arch=i386 _CIatan2() +@ cdecl -arch=i386 _CIcos() +@ cdecl -arch=i386 _CIcosh() +@ cdecl -arch=i386 _CIexp() +@ cdecl -arch=i386 _CIfmod() +@ cdecl -arch=i386 _CIlog() +@ cdecl -arch=i386 _CIlog10() +@ cdecl -arch=i386 _CIpow() +@ cdecl -arch=i386 _CIsin() +@ cdecl -arch=i386 _CIsinh() +@ cdecl -arch=i386 _CIsqrt() +@ cdecl -arch=i386 _CItan() +@ cdecl -arch=i386 _CItanh() +@ stdcall _CxxThrowException(long long) +@ extern _HUGE +@ cdecl _XcptFilter(long ptr) +@ cdecl -i386 __CxxFrameHandler(ptr ptr ptr ptr) +@ stdcall __CxxLongjmpUnwind(ptr) +@ cdecl __STRINGTOLD(ptr ptr str long) +@ extern __argc +@ extern __argv +@ cdecl __dllonexit(ptr ptr ptr) +@ cdecl __doserrno() +@ cdecl __fpecode() @ cdecl __getmainargs(ptr ptr ptr long long) MSVCRT20__getmainargs -@ extern __initenv msvcrt.__initenv -@ cdecl __isascii(long) msvcrt.__isascii -@ cdecl __iscsym(long) msvcrt.__iscsym -@ cdecl __iscsymf(long) msvcrt.__iscsymf -@ cdecl __lconv_init() msvcrt.__lconv_init -@ extern __mb_cur_max msvcrt.__mb_cur_max -@ cdecl -arch=i386 __p___argc() msvcrt.__p___argc -@ cdecl -arch=i386 __p___argv() msvcrt.__p___argv -@ cdecl -arch=i386 __p___initenv() msvcrt.__p___initenv -@ cdecl -arch=i386 __p___mb_cur_max() msvcrt.__p___mb_cur_max -@ cdecl -arch=i386 __p___wargv() msvcrt.__p___wargv -@ cdecl -arch=i386 __p___winitenv() msvcrt.__p___winitenv -@ cdecl -arch=i386 __p__acmdln() msvcrt.__p__acmdln -@ cdecl -arch=i386 __p__amblksiz() msvcrt.__p__amblksiz -@ cdecl -arch=i386 __p__commode() msvcrt.__p__commode -@ cdecl -arch=i386 __p__daylight() msvcrt.__p__daylight -@ cdecl -arch=i386 __p__environ() msvcrt.__p__environ -@ cdecl -arch=i386 __p__fmode() msvcrt.__p__fmode -@ cdecl -arch=i386 __p__iob() msvcrt.__p__iob -@ cdecl -arch=i386 __p__mbctype() msvcrt.__p__mbctype -@ cdecl -arch=i386 __p__osver() msvcrt.__p__osver -@ cdecl -arch=i386 __p__pctype() msvcrt.__p__pctype -@ cdecl -arch=i386 __p__pgmptr() msvcrt.__p__pgmptr -@ cdecl -arch=i386 __p__pwctype() msvcrt.__p__pwctype -@ cdecl -arch=i386 __p__timezone() msvcrt.__p__timezone -@ cdecl -arch=i386 __p__tzname() msvcrt.__p__tzname -@ cdecl -arch=i386 __p__wcmdln() msvcrt.__p__wcmdln -@ cdecl -arch=i386 __p__wenviron() msvcrt.__p__wenviron -@ cdecl -arch=i386 __p__winmajor() msvcrt.__p__winmajor -@ cdecl -arch=i386 __p__winminor() msvcrt.__p__winminor -@ cdecl -arch=i386 __p__winver() msvcrt.__p__winver -@ cdecl -arch=i386 __p__wpgmptr() msvcrt.__p__wpgmptr -@ cdecl __pxcptinfoptrs() msvcrt.__pxcptinfoptrs -@ cdecl __threadhandle() msvcrt.__threadhandle -@ cdecl __threadid() msvcrt.__threadid -@ cdecl __toascii(long) msvcrt.__toascii -@ extern __wargv msvcrt.__wargv +@ extern __initenv +@ cdecl __isascii(long) +@ cdecl __iscsym(long) +@ cdecl __iscsymf(long) +@ cdecl __lconv_init() +@ extern __mb_cur_max +@ cdecl -arch=i386 __p___argc() +@ cdecl -arch=i386 __p___argv() +@ cdecl -arch=i386 __p___initenv() +@ cdecl -arch=i386 __p___mb_cur_max() +@ cdecl -arch=i386 __p___wargv() +@ cdecl -arch=i386 __p___winitenv() +@ cdecl -arch=i386 __p__acmdln() +@ cdecl -arch=i386 __p__amblksiz() +@ cdecl -arch=i386 __p__commode() +@ cdecl -arch=i386 __p__daylight() +@ cdecl -arch=i386 __p__environ() +@ cdecl -arch=i386 __p__fmode() +@ cdecl -arch=i386 __p__iob() +@ cdecl -arch=i386 __p__mbctype() +@ cdecl -arch=i386 __p__osver() +@ cdecl -arch=i386 __p__pctype() +@ cdecl -arch=i386 __p__pgmptr() +@ cdecl -arch=i386 __p__pwctype() +@ cdecl -arch=i386 __p__timezone() +@ cdecl -arch=i386 __p__tzname() +@ cdecl -arch=i386 __p__wcmdln() +@ cdecl -arch=i386 __p__wenviron() +@ cdecl -arch=i386 __p__winmajor() +@ cdecl -arch=i386 __p__winminor() +@ cdecl -arch=i386 __p__winver() +@ cdecl -arch=i386 __p__wpgmptr() +@ cdecl __pxcptinfoptrs() +@ cdecl __threadhandle() kernel32.GetCurrentThread +@ cdecl __threadid() kernel32.GetCurrentThreadId +@ cdecl __toascii(long) +@ extern __wargv @ cdecl __wgetmainargs(ptr ptr ptr long long) MSVCRT20__wgetmainargs -@ extern __winitenv msvcrt.__winitenv -@ cdecl _abnormal_termination() msvcrt._abnormal_termination -@ cdecl _access(str long) msvcrt._access -@ extern _acmdln msvcrt._acmdln -@ stdcall _adj_fdiv_m16i(long) msvcrt._adj_fdiv_m16i -@ stdcall _adj_fdiv_m32(long) msvcrt._adj_fdiv_m32 -@ stdcall _adj_fdiv_m32i(long) msvcrt._adj_fdiv_m32i -@ stdcall _adj_fdiv_m64(long long) msvcrt._adj_fdiv_m64 -@ cdecl _adj_fdiv_r() msvcrt._adj_fdiv_r -@ stdcall _adj_fdivr_m16i(long) msvcrt._adj_fdivr_m16i -@ stdcall _adj_fdivr_m32(long) msvcrt._adj_fdivr_m32 -@ stdcall _adj_fdivr_m32i(long) msvcrt._adj_fdivr_m32i -@ stdcall _adj_fdivr_m64(long long) msvcrt._adj_fdivr_m64 -@ cdecl _adj_fpatan() msvcrt._adj_fpatan -@ cdecl _adj_fprem() msvcrt._adj_fprem -@ cdecl _adj_fprem1() msvcrt._adj_fprem1 -@ cdecl _adj_fptan() msvcrt._adj_fptan -@ cdecl _adjust_fdiv() msvcrt._adjust_fdiv -@ extern _aexit_rtn msvcrt._aexit_rtn -@ cdecl _amsg_exit(long) msvcrt._amsg_exit -@ cdecl _assert(str str long) msvcrt._assert -@ cdecl _atodbl(ptr str) msvcrt._atodbl -@ cdecl _atoldbl(ptr str) msvcrt._atoldbl -@ cdecl _beep(long long) msvcrt._beep -@ cdecl _beginthread(ptr long ptr) msvcrt._beginthread -@ cdecl _beginthreadex(ptr long ptr ptr long ptr) msvcrt._beginthreadex -@ cdecl _c_exit() msvcrt._c_exit -@ cdecl _cabs(long) msvcrt._cabs -@ cdecl _cexit() msvcrt._cexit -@ cdecl _cgets(str) msvcrt._cgets -@ cdecl _chdir(str) msvcrt._chdir -@ cdecl _chdrive(long) msvcrt._chdrive -@ cdecl _chgsign( double ) msvcrt._chgsign -@ cdecl _chmod(str long) msvcrt._chmod -@ cdecl _chsize(long long) msvcrt._chsize -@ cdecl _clearfp() msvcrt._clearfp -@ cdecl _close(long) msvcrt._close -@ cdecl _commit(long) msvcrt._commit -@ extern _commode msvcrt._commode -@ cdecl _control87(long long) msvcrt._control87 -@ cdecl _controlfp(long long) msvcrt._controlfp -@ cdecl _copysign( double double ) msvcrt._copysign -@ varargs _cprintf(str) msvcrt._cprintf -@ cdecl _cputs(str) msvcrt._cputs -@ cdecl _creat(str long) msvcrt._creat -@ varargs _cscanf(str) msvcrt._cscanf -@ extern _ctype msvcrt._ctype -@ cdecl _cwait(ptr long long) msvcrt._cwait -@ extern _daylight msvcrt._daylight -@ cdecl _dup(long) msvcrt._dup -@ cdecl _dup2(long long) msvcrt._dup2 -@ cdecl _ecvt( double long ptr ptr) msvcrt._ecvt -@ cdecl _endthread() msvcrt._endthread -@ cdecl _endthreadex(long) msvcrt._endthreadex -@ extern _environ msvcrt._environ -@ cdecl _eof(long) msvcrt._eof -@ cdecl _errno() msvcrt._errno -@ cdecl _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2 -@ cdecl _except_handler3(ptr ptr ptr ptr) msvcrt._except_handler3 -@ varargs _execl(str str) msvcrt._execl -@ varargs _execle(str str) msvcrt._execle -@ varargs _execlp(str str) msvcrt._execlp -@ varargs _execlpe(str str) msvcrt._execlpe -@ cdecl _execv(str ptr) msvcrt._execv -@ cdecl _execve(str ptr ptr) msvcrt._execve -@ cdecl _execvp(str ptr) msvcrt._execvp -@ cdecl _execvpe(str ptr ptr) msvcrt._execvpe -@ cdecl _exit(long) msvcrt._exit -@ cdecl _expand(ptr long) msvcrt._expand -@ cdecl _fcloseall() msvcrt._fcloseall -@ cdecl _fcvt( double long ptr ptr) msvcrt._fcvt -@ cdecl _fdopen(long str) msvcrt._fdopen -@ cdecl _fgetchar() msvcrt._fgetchar -@ cdecl _fgetwchar() msvcrt._fgetwchar -@ cdecl _filbuf(ptr) msvcrt._filbuf -@ extern _fileinfo msvcrt._fileinfo -@ cdecl _filelength(long) msvcrt._filelength -@ cdecl _fileno(ptr) msvcrt._fileno -@ cdecl _findclose(long) msvcrt._findclose -@ cdecl _findfirst(str ptr) msvcrt._findfirst -@ cdecl _findnext(long ptr) msvcrt._findnext -@ cdecl _finite( double ) msvcrt._finite -@ cdecl _flsbuf(long ptr) msvcrt._flsbuf -@ cdecl _flushall() msvcrt._flushall -@ extern _fmode msvcrt._fmode -@ cdecl _fpclass(double) msvcrt._fpclass -@ cdecl _fpieee_flt(long ptr ptr) msvcrt._fpieee_flt -@ cdecl _fpreset() msvcrt._fpreset -@ cdecl _fputchar(long) msvcrt._fputchar -@ cdecl _fputwchar(long) msvcrt._fputwchar -@ cdecl _fsopen(str str long) msvcrt._fsopen -@ cdecl _fstat(long ptr) msvcrt._fstat -@ cdecl _ftime(ptr) msvcrt._ftime -@ cdecl -ret64 _ftol() msvcrt._ftol -@ cdecl _fullpath(ptr str long) msvcrt._fullpath -@ cdecl _futime(long ptr) msvcrt._futime -@ cdecl _gcvt( double long str) msvcrt._gcvt -@ cdecl _get_osfhandle(long) msvcrt._get_osfhandle -@ cdecl _getch() msvcrt._getch -@ cdecl _getche() msvcrt._getche -@ cdecl _getcwd(str long) msvcrt._getcwd -@ cdecl _getdcwd(long str long) msvcrt._getdcwd -@ cdecl _getdiskfree(long ptr) msvcrt._getdiskfree -@ cdecl _getdllprocaddr(long str long) msvcrt._getdllprocaddr -@ cdecl _getdrive() msvcrt._getdrive -@ cdecl _getdrives() msvcrt._getdrives -@ cdecl _getmbcp() msvcrt._getmbcp -@ cdecl _getpid() msvcrt._getpid -@ cdecl _getsystime(ptr) msvcrt._getsystime -@ cdecl _getw(ptr) msvcrt._getw -@ cdecl _getws(ptr) msvcrt._getws -@ cdecl _global_unwind2(ptr) msvcrt._global_unwind2 -@ cdecl _heapadd(ptr long) msvcrt._heapadd -@ cdecl _heapchk() msvcrt._heapchk -@ cdecl _heapmin() msvcrt._heapmin -@ cdecl _heapset(long) msvcrt._heapset -@ cdecl _heapused(ptr ptr) msvcrt._heapused -@ cdecl _heapwalk(ptr) msvcrt._heapwalk -@ cdecl _hypot(double double) msvcrt._hypot -@ cdecl _initterm(ptr ptr) msvcrt._initterm -@ extern _iob msvcrt._iob -@ cdecl _isatty(long) msvcrt._isatty -@ cdecl _isctype(long long) msvcrt._isctype -@ cdecl _ismbbalnum(long) msvcrt._ismbbalnum -@ cdecl _ismbbalpha(long) msvcrt._ismbbalpha -@ cdecl _ismbbgraph(long) msvcrt._ismbbgraph -@ cdecl _ismbbkalnum(long) msvcrt._ismbbkalnum -@ cdecl _ismbbkana(long) msvcrt._ismbbkana -@ cdecl _ismbbkprint(long) msvcrt._ismbbkprint -@ cdecl _ismbbkpunct(long) msvcrt._ismbbkpunct -@ cdecl _ismbblead(long) msvcrt._ismbblead -@ cdecl _ismbbprint(long) msvcrt._ismbbprint -@ cdecl _ismbbpunct(long) msvcrt._ismbbpunct -@ cdecl _ismbbtrail(long) msvcrt._ismbbtrail -@ cdecl _ismbcalnum(long) msvcrt._ismbcalnum -@ cdecl _ismbcalpha(long) msvcrt._ismbcalpha -@ cdecl _ismbcdigit(long) msvcrt._ismbcdigit -@ cdecl _ismbcgraph(long) msvcrt._ismbcgraph -@ cdecl _ismbchira(long) msvcrt._ismbchira -@ cdecl _ismbckata(long) msvcrt._ismbckata -@ cdecl _ismbcl0(long) msvcrt._ismbcl0 -@ cdecl _ismbcl1(long) msvcrt._ismbcl1 -@ cdecl _ismbcl2(long) msvcrt._ismbcl2 -@ cdecl _ismbclegal(long) msvcrt._ismbclegal -@ cdecl _ismbclower(long) msvcrt._ismbclower -@ cdecl _ismbcprint(long) msvcrt._ismbcprint -@ cdecl _ismbcpunct(long) msvcrt._ismbcpunct -@ cdecl _ismbcspace(long) msvcrt._ismbcspace -@ cdecl _ismbcsymbol(long) msvcrt._ismbcsymbol -@ cdecl _ismbcupper(long) msvcrt._ismbcupper -@ cdecl _ismbslead(ptr ptr) msvcrt._ismbslead -@ cdecl _ismbstrail(ptr ptr) msvcrt._ismbstrail -@ cdecl _isnan( double ) msvcrt._isnan -@ cdecl _itoa(long ptr long) msvcrt._itoa -@ cdecl _itow(long ptr long) msvcrt._itow -@ cdecl _j0(double) msvcrt._j0 -@ cdecl _j1(double) msvcrt._j1 -@ cdecl _jn(long double) msvcrt._jn -@ cdecl _kbhit() msvcrt._kbhit -@ cdecl _lfind(ptr ptr ptr long ptr) msvcrt._lfind -@ cdecl _loaddll(str) msvcrt._loaddll -@ cdecl _local_unwind2(ptr long) msvcrt._local_unwind2 -@ cdecl _locking(long long long) msvcrt._locking -@ cdecl _logb(double) msvcrt._logb -@ cdecl _longjmpex(ptr long) msvcrt._longjmpex -@ cdecl _lrotl(long long) msvcrt._lrotl -@ cdecl _lrotr(long long) msvcrt._lrotr -@ cdecl _lsearch(ptr ptr long long ptr) msvcrt._lsearch -@ cdecl _lseek(long long long) msvcrt._lseek -@ cdecl _ltoa(long ptr long) msvcrt._ltoa -@ cdecl _ltow(long ptr long) msvcrt._ltow -@ cdecl _makepath(str str str str str) msvcrt._makepath -@ cdecl _matherr(ptr) msvcrt._matherr -@ cdecl _mbbtombc(long) msvcrt._mbbtombc -@ cdecl _mbbtype(long long) msvcrt._mbbtype -@ cdecl _mbccpy(str str) msvcrt._mbccpy -@ cdecl _mbcjistojms(long) msvcrt._mbcjistojms -@ cdecl _mbcjmstojis(long) msvcrt._mbcjmstojis -@ cdecl _mbclen(ptr) msvcrt._mbclen -@ cdecl _mbctohira(long) msvcrt._mbctohira -@ cdecl _mbctokata(long) msvcrt._mbctokata -@ cdecl _mbctolower(long) msvcrt._mbctolower -@ cdecl _mbctombb(long) msvcrt._mbctombb -@ cdecl _mbctoupper(long) msvcrt._mbctoupper -@ extern _mbctype msvcrt._mbctype -@ cdecl _mbsbtype(str long) msvcrt._mbsbtype -@ cdecl _mbscat(str str) msvcrt._mbscat -@ cdecl _mbschr(str long) msvcrt._mbschr -@ cdecl _mbscmp(str str) msvcrt._mbscmp -@ cdecl _mbscoll(str str) msvcrt._mbscoll -@ cdecl _mbscpy(ptr str) msvcrt._mbscpy -@ cdecl _mbscspn(str str) msvcrt._mbscspn -@ cdecl _mbsdec(ptr ptr) msvcrt._mbsdec -@ cdecl _mbsdup(str) msvcrt._mbsdup -@ cdecl _mbsicmp(str str) msvcrt._mbsicmp -@ cdecl _mbsicoll(str str) msvcrt._mbsicoll -@ cdecl _mbsinc(str) msvcrt._mbsinc -@ cdecl _mbslen(str) msvcrt._mbslen -@ cdecl _mbslwr(str) msvcrt._mbslwr -@ cdecl _mbsnbcat(str str long) msvcrt._mbsnbcat -@ cdecl _mbsnbcmp(str str long) msvcrt._mbsnbcmp -@ cdecl _mbsnbcnt(ptr long) msvcrt._mbsnbcnt -@ cdecl _mbsnbcoll(str str long) msvcrt._mbsnbcoll -@ cdecl _mbsnbcpy(ptr str long) msvcrt._mbsnbcpy -@ cdecl _mbsnbicmp(str str long) msvcrt._mbsnbicmp -@ cdecl _mbsnbicoll(str str long) msvcrt._mbsnbicoll -@ cdecl _mbsnbset(str long long) msvcrt._mbsnbset -@ cdecl _mbsncat(str str long) msvcrt._mbsncat -@ cdecl _mbsnccnt(str long) msvcrt._mbsnccnt -@ cdecl _mbsncmp(str str long) msvcrt._mbsncmp -@ cdecl _mbsncoll(str str long) msvcrt._mbsncoll -@ cdecl _mbsncpy(str str long) msvcrt._mbsncpy -@ cdecl _mbsnextc(str) msvcrt._mbsnextc -@ cdecl _mbsnicmp(str str long) msvcrt._mbsnicmp -@ cdecl _mbsnicoll(str str long) msvcrt._mbsnicoll -@ cdecl _mbsninc(str long) msvcrt._mbsninc -@ cdecl _mbsnset(str long long) msvcrt._mbsnset -@ cdecl _mbspbrk(str str) msvcrt._mbspbrk -@ cdecl _mbsrchr(str long) msvcrt._mbsrchr -@ cdecl _mbsrev(str) msvcrt._mbsrev -@ cdecl _mbsset(str long) msvcrt._mbsset -@ cdecl _mbsspn(str str) msvcrt._mbsspn -@ cdecl _mbsspnp(str str) msvcrt._mbsspnp -@ cdecl _mbsstr(str str) msvcrt._mbsstr -@ cdecl _mbstok(str str) msvcrt._mbstok -@ cdecl _mbstrlen(str) msvcrt._mbstrlen -@ cdecl _mbsupr(str) msvcrt._mbsupr -@ cdecl _memccpy(ptr ptr long long) msvcrt._memccpy -@ cdecl _memicmp(str str long) msvcrt._memicmp -@ cdecl _mkdir(str) msvcrt._mkdir -@ cdecl _mktemp(str) msvcrt._mktemp -@ cdecl _msize(ptr) msvcrt._msize +@ extern __winitenv +@ cdecl _abnormal_termination() +@ cdecl _access(str long) +@ extern _acmdln +@ stdcall _adj_fdiv_m16i(long) +@ stdcall _adj_fdiv_m32(long) +@ stdcall _adj_fdiv_m32i(long) +@ stdcall _adj_fdiv_m64(double) +@ cdecl _adj_fdiv_r() +@ stdcall _adj_fdivr_m16i(long) +@ stdcall _adj_fdivr_m32(long) +@ stdcall _adj_fdivr_m32i(long) +@ stdcall _adj_fdivr_m64(double) +@ cdecl _adj_fpatan() +@ cdecl _adj_fprem() +@ cdecl _adj_fprem1() +@ cdecl _adj_fptan() +@ extern _adjust_fdiv +@ extern _aexit_rtn +@ cdecl _amsg_exit(long) +@ cdecl _assert(str str long) +@ cdecl _atodbl(ptr str) +@ cdecl _atoldbl(ptr str) +@ cdecl _beep(long long) +@ cdecl _beginthread(ptr long ptr) +@ cdecl _beginthreadex(ptr long ptr ptr long ptr) +@ cdecl _c_exit() +@ cdecl _cabs(long) +@ cdecl _cexit() +@ cdecl _cgets(str) +@ cdecl _chdir(str) +@ cdecl _chdrive(long) +@ cdecl _chgsign(double) +@ cdecl _chmod(str long) +@ cdecl _chsize(long long) +@ cdecl _clearfp() +@ cdecl _close(long) +@ cdecl _commit(long) +@ extern _commode +@ cdecl _control87(long long) +@ cdecl _controlfp(long long) +@ cdecl _copysign( double double ) +@ varargs _cprintf(str) +@ cdecl _cputs(str) +@ cdecl _creat(str long) +@ varargs _cscanf(str) +@ extern _ctype +@ cdecl _cwait(ptr long long) +@ extern _daylight +@ cdecl _dup(long) +@ cdecl _dup2(long long) +@ cdecl _ecvt(double long ptr ptr) +@ cdecl _endthread() +@ cdecl _endthreadex(long) +@ extern _environ +@ cdecl _eof(long) +@ cdecl _errno() +@ cdecl _except_handler2(ptr ptr ptr ptr) +@ cdecl _except_handler3(ptr ptr ptr ptr) +@ varargs _execl(str str) +@ varargs _execle(str str) +@ varargs _execlp(str str) +@ varargs _execlpe(str str) +@ cdecl _execv(str ptr) +@ cdecl _execve(str ptr ptr) +@ cdecl _execvp(str ptr) +@ cdecl _execvpe(str ptr ptr) +@ cdecl _exit(long) +@ cdecl _expand(ptr long) +@ cdecl _fcloseall() +@ cdecl _fcvt(double long ptr ptr) +@ cdecl _fdopen(long str) +@ cdecl _fgetchar() +@ cdecl _fgetwchar() +@ cdecl _filbuf(ptr) +@ extern _fileinfo +@ cdecl _filelength(long) +@ cdecl _fileno(ptr) +@ cdecl _findclose(long) +@ cdecl _findfirst(str ptr) +@ cdecl _findnext(long ptr) +@ cdecl _finite( double ) +@ cdecl _flsbuf(long ptr) +@ cdecl _flushall() +@ extern _fmode +@ cdecl _fpclass(double) +@ cdecl _fpieee_flt(long ptr ptr) +@ cdecl _fpreset() +@ cdecl _fputchar(long) +@ cdecl _fputwchar(long) +@ cdecl _fsopen(str str long) +@ cdecl _fstat(long ptr) +@ cdecl _ftime(ptr) +@ cdecl -ret64 _ftol() +@ cdecl _fullpath(ptr str long) +@ cdecl _futime(long ptr) +@ cdecl _gcvt(double long str) +@ cdecl _get_osfhandle(long) +@ cdecl _getch() +@ cdecl _getche() +@ cdecl _getcwd(str long) +@ cdecl _getdcwd(long str long) +@ cdecl _getdiskfree(long ptr) +@ cdecl _getdllprocaddr(long str long) +@ cdecl _getdrive() +@ cdecl _getdrives() kernel32.GetLogicalDrives +@ cdecl _getmbcp() +@ cdecl _getpid() kernel32.GetCurrentProcessId +@ cdecl _getsystime(ptr) +@ cdecl _getw(ptr) +@ cdecl _getws(ptr) +@ cdecl _global_unwind2(ptr) +@ cdecl _heapadd(ptr long) +@ cdecl _heapchk() +@ cdecl _heapmin() +@ cdecl _heapset(long) +@ cdecl _heapused(ptr ptr) +@ cdecl _heapwalk(ptr) +@ cdecl _hypot(double double) +@ cdecl _initterm(ptr ptr) +@ extern _iob +@ cdecl _isatty(long) +@ cdecl _isctype(long long) +@ cdecl _ismbbalnum(long) +@ cdecl _ismbbalpha(long) +@ cdecl _ismbbgraph(long) +@ cdecl _ismbbkalnum(long) +@ cdecl _ismbbkana(long) +@ cdecl _ismbbkprint(long) +@ cdecl _ismbbkpunct(long) +@ cdecl _ismbblead(long) +@ cdecl _ismbbprint(long) +@ cdecl _ismbbpunct(long) +@ cdecl _ismbbtrail(long) +@ cdecl _ismbcalnum(long) +@ cdecl _ismbcalpha(long) +@ cdecl _ismbcdigit(long) +@ cdecl _ismbcgraph(long) +@ cdecl _ismbchira(long) +@ cdecl _ismbckata(long) +@ cdecl _ismbcl0(long) +@ cdecl _ismbcl1(long) +@ cdecl _ismbcl2(long) +@ cdecl _ismbclegal(long) +@ cdecl _ismbclower(long) +@ cdecl _ismbcprint(long) +@ cdecl _ismbcpunct(long) +@ cdecl _ismbcspace(long) +@ cdecl _ismbcsymbol(long) +@ cdecl _ismbcupper(long) +@ cdecl _ismbslead(ptr ptr) +@ cdecl _ismbstrail(ptr ptr) +@ cdecl _isnan(double) +@ cdecl _itoa(long ptr long) +@ cdecl _itow(long ptr long) +@ cdecl _j0(double) +@ cdecl _j1(double) +@ cdecl _jn(long double) +@ cdecl _kbhit() +@ cdecl _lfind(ptr ptr ptr long ptr) +@ cdecl _loaddll(str) +@ cdecl _local_unwind2(ptr long) +@ cdecl _locking(long long long) +@ cdecl _logb(double) +@ cdecl _longjmpex(ptr long) longjmp +@ cdecl _lrotl(long long) +@ cdecl _lrotr(long long) +@ cdecl _lsearch(ptr ptr long long ptr) +@ cdecl _lseek(long long long) +@ cdecl _ltoa(long ptr long) +@ cdecl _ltow(long ptr long) +@ cdecl _makepath(ptr str str str str) +@ cdecl _matherr(ptr) +@ cdecl _mbbtombc(long) +@ cdecl _mbbtype(long long) +@ cdecl _mbccpy(str str) +@ cdecl _mbcjistojms(long) +@ cdecl _mbcjmstojis(long) +@ cdecl _mbclen(ptr) +@ cdecl _mbctohira(long) +@ cdecl _mbctokata(long) +@ cdecl _mbctolower(long) +@ cdecl _mbctombb(long) +@ cdecl _mbctoupper(long) +@ extern _mbctype +@ cdecl _mbsbtype(str long) +@ cdecl _mbscat(str str) +@ cdecl _mbschr(str long) +@ cdecl _mbscmp(str str) +@ cdecl _mbscoll(str str) +@ cdecl _mbscpy(ptr str) +@ cdecl _mbscspn(str str) +@ cdecl _mbsdec(ptr ptr) +@ cdecl _mbsdup(str) +@ cdecl _mbsicmp(str str) +@ cdecl _mbsicoll(str str) +@ cdecl _mbsinc(str) +@ cdecl _mbslen(str) +@ cdecl _mbslwr(str) +@ cdecl _mbsnbcat(str str long) +@ cdecl _mbsnbcmp(str str long) +@ cdecl _mbsnbcnt(ptr long) +@ cdecl _mbsnbcoll(str str long) +@ cdecl _mbsnbcpy(ptr str long) +@ cdecl _mbsnbicmp(str str long) +@ cdecl _mbsnbicoll(str str long) +@ cdecl _mbsnbset(str long long) +@ cdecl _mbsncat(str str long) +@ cdecl _mbsnccnt(str long) +@ cdecl _mbsncmp(str str long) +@ cdecl _mbsncoll(str str long) +@ cdecl _mbsncpy(str str long) +@ cdecl _mbsnextc(str) +@ cdecl _mbsnicmp(str str long) +@ cdecl _mbsnicoll(str str long) +@ cdecl _mbsninc(str long) +@ cdecl _mbsnset(str long long) +@ cdecl _mbspbrk(str str) +@ cdecl _mbsrchr(str long) +@ cdecl _mbsrev(str) +@ cdecl _mbsset(str long) +@ cdecl _mbsspn(str str) +@ cdecl _mbsspnp(str str) +@ cdecl _mbsstr(str str) +@ cdecl _mbstok(str str) +@ cdecl _mbstrlen(str) +@ cdecl _mbsupr(str) +@ cdecl _memccpy(ptr ptr long long) +@ cdecl _memicmp(str str long) +@ cdecl _mkdir(str) +@ cdecl _mktemp(str) +@ cdecl _msize(ptr) @ stub _mtlock @ stub _mtunlock -@ cdecl _nextafter(double double) msvcrt._nextafter -@ cdecl _onexit(ptr) msvcrt._onexit -@ varargs _open(str long) msvcrt._open -@ cdecl _open_osfhandle(long long) msvcrt._open_osfhandle -@ extern _osver msvcrt._osver -@ cdecl _pclose(ptr) msvcrt._pclose -@ extern _pctype msvcrt._pctype -@ extern _pgmptr msvcrt._pgmptr -@ cdecl _pipe(ptr long long) msvcrt._pipe -@ cdecl _popen(str str) msvcrt._popen -@ cdecl _purecall() msvcrt._purecall -@ cdecl _putch(long) msvcrt._putch -@ cdecl _putenv(str) msvcrt._putenv -@ cdecl _putw(long ptr) msvcrt._putw -@ cdecl _putws(wstr) msvcrt._putws -@ extern _pwctype msvcrt._pwctype -@ cdecl _read(long ptr long) msvcrt._read -@ cdecl _rmdir(str) msvcrt._rmdir -@ cdecl _rmtmp() msvcrt._rmtmp -@ cdecl _rotl(long long) msvcrt._rotl -@ cdecl _rotr(long long) msvcrt._rotr -@ cdecl _safe_fdiv() msvcrt._safe_fdiv -@ cdecl _safe_fdivr() msvcrt._safe_fdivr -@ cdecl _safe_fprem() msvcrt._safe_fprem -@ cdecl _safe_fprem1() msvcrt._safe_fprem1 -@ cdecl _scalb( double long) msvcrt._scalb -@ cdecl _searchenv(str str ptr) msvcrt._searchenv -@ stdcall -i386 __seh_longjmp_unwind@4(ptr) msvcrt._seh_longjmp_unwind -@ cdecl _seterrormode(long) msvcrt._seterrormode -@ cdecl -i386 _setjmp(ptr) msvcrt._setjmp -@ cdecl -i386 _setjmp3(ptr long) msvcrt._setjmp3 -@ cdecl _setmbcp(long) msvcrt._setmbcp -@ cdecl _setmode(long long) msvcrt._setmode -@ cdecl _setsystime(ptr long) msvcrt._setsystime -@ cdecl _sleep(long) msvcrt._sleep -@ varargs _snprintf(str long str) msvcrt._snprintf -@ varargs _snwprintf(wstr long wstr) msvcrt._snwprintf -@ varargs _sopen(str long long) msvcrt._sopen -@ varargs _spawnl(long str str) msvcrt._spawnl -@ varargs _spawnle(long str str) msvcrt._spawnle -@ varargs _spawnlp(long str str) msvcrt._spawnlp -@ varargs _spawnlpe(long str str) msvcrt._spawnlpe -@ cdecl _spawnv(long str ptr) msvcrt._spawnv -@ cdecl _spawnve(long str ptr ptr) msvcrt._spawnve -@ cdecl _spawnvp(long str ptr) msvcrt._spawnvp -@ cdecl _spawnvpe(long str ptr ptr) msvcrt._spawnvpe -@ cdecl _splitpath(str ptr ptr ptr ptr) msvcrt._splitpath -@ cdecl _stat(str ptr) msvcrt._stat -@ cdecl _statusfp() msvcrt._statusfp -@ cdecl _strcmpi(str str) msvcrt._strcmpi -@ cdecl _strdate(ptr) msvcrt._strdate -@ cdecl _strdup(str) msvcrt._strdup -@ cdecl _strerror(long) msvcrt._strerror -@ cdecl _stricmp(str str) msvcrt._stricmp -@ cdecl _stricoll(str str) msvcrt._stricoll -@ cdecl _strlwr(str) msvcrt._strlwr -@ cdecl _strncoll(str str long) msvcrt._strncoll -@ cdecl _strnicmp(str str long) msvcrt._strnicmp -@ cdecl _strnicoll(str str long) msvcrt._strnicoll -@ cdecl _strnset(str long long) msvcrt._strnset -@ cdecl _strrev(str) msvcrt._strrev -@ cdecl _strset(str long) msvcrt._strset -@ cdecl _strtime(ptr) msvcrt._strtime -@ cdecl _strupr(str) msvcrt._strupr -@ cdecl _swab(str str long) msvcrt._swab -@ extern _sys_errlist msvcrt._sys_errlist -@ extern _sys_nerr msvcrt._sys_nerr -@ cdecl _tccpy(str str) msvcrt._mbccpy -@ cdecl _tclen(ptr) msvcrt._mbclen -@ cdecl _tcschr(str long) msvcrt._mbschr -@ cdecl _tcsclen(str) msvcrt._mbslen -@ cdecl _tcscmp(str str) msvcrt._mbscmp -@ cdecl _tcscspn(str str) msvcrt._mbscspn -@ cdecl _tcsdec(ptr ptr) msvcrt._mbsdec -@ cdecl _tcsicmp(str str) msvcrt._mbsicmp -@ cdecl _tcsinc(str) msvcrt._mbsinc -@ cdecl _tcslwr(str) msvcrt._mbslwr -@ cdecl _tcsnbcnt(ptr long) msvcrt._mbsnbcnt -@ cdecl _tcsncat(str str long) msvcrt._mbsnbcat -@ cdecl _tcsnccat(str str long) msvcrt._mbsncat -@ cdecl _tcsnccmp(str str long) msvcrt._mbsncmp -@ cdecl _tcsnccnt(str long) msvcrt._mbsnccnt -@ cdecl _tcsnccpy(str str long) msvcrt._mbsncpy -@ cdecl _tcsncicmp(str str long) msvcrt._mbsnicmp -@ cdecl _tcsncmp(str str long) msvcrt._mbsnbcmp -@ cdecl _tcsncpy(ptr str long) msvcrt._mbsnbcpy -@ cdecl _tcsncset(str long long) msvcrt._mbsnset -@ cdecl _tcsnextc(str) msvcrt._mbsnextc -@ cdecl _tcsnicmp(str str long) msvcrt._mbsnbicmp -@ cdecl _tcsninc(str long) msvcrt._mbsninc -@ cdecl _tcsnset(str long long) msvcrt._mbsnbset -@ cdecl _tcspbrk(str str) msvcrt._mbspbrk -@ cdecl _tcsrchr(str long) msvcrt._mbsrchr -@ cdecl _tcsrev(str) msvcrt._mbsrev -@ cdecl _tcsset(str long) msvcrt._mbsset -@ cdecl _tcsspn(str str) msvcrt._mbsspn -@ cdecl _tcsspnp(str str) msvcrt._mbsspnp -@ cdecl _tcsstr(str str) msvcrt._mbsstr -@ cdecl _tcstok(str str) msvcrt._mbstok -@ cdecl _tcsupr(str) msvcrt._mbsupr -@ cdecl _tell(long) msvcrt._tell -@ cdecl _tempnam(str str) msvcrt._tempnam -@ extern _timezone msvcrt._timezone -@ cdecl _tolower(long) msvcrt._tolower -@ cdecl _toupper(long) msvcrt._toupper -@ extern _tzname msvcrt._tzname -@ cdecl _tzset() msvcrt._tzset -@ cdecl _ultoa(long ptr long) msvcrt._ultoa -@ cdecl _ultow(long ptr long) msvcrt._ultow -@ cdecl _umask(long) msvcrt._umask -@ cdecl _ungetch(long) msvcrt._ungetch -@ cdecl _unlink(str) msvcrt._unlink -@ cdecl _unloaddll(long) msvcrt._unloaddll -@ cdecl _utime(str ptr) msvcrt._utime -@ cdecl _vsnprintf(ptr long ptr ptr) msvcrt._vsnprintf -@ cdecl _vsnwprintf(ptr long wstr long) msvcrt._vsnwprintf -@ cdecl _waccess(wstr long) msvcrt._waccess -@ cdecl _wasctime(ptr) msvcrt._wasctime -@ cdecl _wchdir(wstr) msvcrt._wchdir -@ cdecl _wchmod(wstr long) msvcrt._wchmod -@ extern _wcmdln msvcrt._wcmdln -@ cdecl _wcreat(wstr long) msvcrt._wcreat -@ cdecl _wcsdup(wstr) msvcrt._wcsdup -@ cdecl _wcsicmp(wstr wstr) msvcrt._wcsicmp -@ cdecl _wcsicoll(wstr wstr) msvcrt._wcsicoll -@ cdecl _wcslwr(wstr) msvcrt._wcslwr -@ cdecl _wcsncoll(wstr wstr long) msvcrt._wcsncoll -@ cdecl _wcsnicmp(wstr wstr long) msvcrt._wcsnicmp -@ cdecl _wcsnicoll(wstr wstr long) msvcrt._wcsnicoll -@ cdecl _wcsnset(wstr long long) msvcrt._wcsnset -@ cdecl _wcsrev(wstr) msvcrt._wcsrev -@ cdecl _wcsset(wstr long) msvcrt._wcsset -@ cdecl _wcsupr(wstr) msvcrt._wcsupr -@ cdecl _wctime(ptr) msvcrt._wctime -@ extern _wenviron msvcrt._wenviron -@ varargs _wexecl(wstr wstr) msvcrt._wexecl -@ varargs _wexecle(wstr wstr) msvcrt._wexecle -@ varargs _wexeclp(wstr wstr) msvcrt._wexeclp -@ varargs _wexeclpe(wstr wstr) msvcrt._wexeclpe -@ varargs _wexecv(wstr ptr) msvcrt._wexecv -@ varargs _wexecve(wstr ptr ptr) msvcrt._wexecve -@ varargs _wexecvp(wstr ptr) msvcrt._wexecvp -@ varargs _wexecvpe(wstr ptr ptr) msvcrt._wexecvpe -@ cdecl _wfdopen(long wstr) msvcrt._wfdopen -@ cdecl _wfindfirst(wstr ptr) msvcrt._wfindfirst -@ cdecl _wfindnext(long ptr) msvcrt._wfindnext -@ cdecl _wfopen(wstr wstr) msvcrt._wfopen -@ cdecl _wfreopen(wstr wstr ptr) msvcrt._wfreopen -@ cdecl _wfsopen(wstr wstr long) msvcrt._wfsopen -@ cdecl _wfullpath(ptr wstr long) msvcrt._wfullpath -@ cdecl _wgetcwd(wstr long) msvcrt._wgetcwd -@ cdecl _wgetdcwd(long wstr long) msvcrt._wgetdcwd -@ cdecl _wgetenv(wstr) msvcrt._wgetenv -@ extern _winmajor msvcrt._winmajor -@ extern _winminor msvcrt._winminor -@ extern _winver msvcrt._winver -@ cdecl _wmakepath(wstr wstr wstr wstr wstr) msvcrt._wmakepath -@ cdecl _wmkdir(wstr) msvcrt._wmkdir -@ cdecl _wmktemp(wstr) msvcrt._wmktemp -@ varargs _wopen(wstr long) msvcrt._wopen -@ cdecl _wperror(wstr) msvcrt._wperror -@ extern _wpgmptr msvcrt._wpgmptr -@ cdecl _wpopen(wstr wstr) msvcrt._wpopen -@ cdecl _wputenv(wstr) msvcrt._wputenv -@ cdecl _wremove(wstr) msvcrt._wremove -@ cdecl _wrename(wstr wstr) msvcrt._wrename -@ cdecl _write(long ptr long) msvcrt._write -@ cdecl _wrmdir(wstr) msvcrt._wrmdir -@ cdecl _wsearchenv(wstr wstr ptr) msvcrt._wsearchenv -@ cdecl _wsetlocale(long wstr) msvcrt._wsetlocale -@ varargs _wsopen(wstr long long) msvcrt._wsopen -@ varargs _wspawnl(long wstr wstr) msvcrt._wspawnl -@ varargs _wspawnle(long wstr wstr) msvcrt._wspawnle -@ varargs _wspawnlp(long wstr wstr) msvcrt._wspawnlp -@ varargs _wspawnlpe(long wstr wstr) msvcrt._wspawnlpe -@ cdecl _wspawnv(long wstr ptr) msvcrt._wspawnv -@ cdecl _wspawnve(long wstr ptr ptr) msvcrt._wspawnve -@ cdecl _wspawnvp(long wstr ptr) msvcrt._wspawnvp -@ cdecl _wspawnvpe(long wstr ptr ptr) msvcrt._wspawnvpe -@ cdecl _wsplitpath(wstr wstr wstr wstr wstr) msvcrt._wsplitpath -@ cdecl _wstat(wstr ptr) msvcrt._wstat -@ cdecl _wstrdate(ptr) msvcrt._wstrdate -@ cdecl _wstrtime(ptr) msvcrt._wstrtime -@ cdecl _wsystem(wstr) msvcrt._wsystem -@ cdecl _wtempnam(wstr wstr) msvcrt._wtempnam -@ cdecl _wtmpnam(ptr) msvcrt._wtmpnam -@ cdecl _wtoi(wstr) msvcrt._wtoi -@ cdecl _wtol(wstr) msvcrt._wtol -@ cdecl _wunlink(wstr) msvcrt._wunlink -@ cdecl _wutime(wstr ptr) msvcrt._wutime -@ cdecl _y0(double) msvcrt._y0 -@ cdecl _y1(double) msvcrt._y1 -@ cdecl _yn(long double ) msvcrt._yn -@ cdecl abort() msvcrt.abort -@ cdecl abs(long) msvcrt.abs -@ cdecl acos(double) msvcrt.acos -@ cdecl asctime(ptr) msvcrt.asctime -@ cdecl asin(double) msvcrt.asin -@ cdecl atan(double) msvcrt.atan -@ cdecl atan2(double double) msvcrt.atan2 -@ cdecl atexit(ptr) msvcrt.atexit -@ cdecl atof(str) msvcrt.atof -@ cdecl atoi(str) msvcrt.atoi -@ cdecl atol(str) msvcrt.atol -@ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch -@ cdecl calloc(long long) msvcrt.calloc -@ cdecl ceil(double) msvcrt.ceil -@ cdecl clearerr(ptr) msvcrt.clearerr -@ cdecl clock() msvcrt.clock -@ cdecl cos(double) msvcrt.cos -@ cdecl cosh(double) msvcrt.cosh -@ cdecl ctime(ptr) msvcrt.ctime -@ cdecl difftime(long long) msvcrt.difftime -@ cdecl div(long long) msvcrt.div -@ cdecl exit(long) msvcrt.exit -@ cdecl exp(double) msvcrt.exp -@ cdecl fabs(double) msvcrt.fabs -@ cdecl fclose(ptr) msvcrt.fclose -@ cdecl feof(ptr) msvcrt.feof -@ cdecl ferror(ptr) msvcrt.ferror -@ cdecl fflush(ptr) msvcrt.fflush -@ cdecl fgetc(ptr) msvcrt.fgetc -@ cdecl fgetpos(ptr ptr) msvcrt.fgetpos -@ cdecl fgets(ptr long ptr) msvcrt.fgets -@ cdecl fgetwc(ptr) msvcrt.fgetwc -@ cdecl fgetws(ptr long ptr) msvcrt.fgetws -@ cdecl floor(double) msvcrt.floor -@ cdecl fmod(double double) msvcrt.fmod -@ cdecl fopen(str str) msvcrt.fopen -@ varargs fprintf(ptr str) msvcrt.fprintf -@ cdecl fputc(long ptr) msvcrt.fputc -@ cdecl fputs(str ptr) msvcrt.fputs -@ cdecl fputwc(long ptr) msvcrt.fputwc -@ cdecl fputws(wstr ptr) msvcrt.fputws -@ cdecl fread(ptr long long ptr) msvcrt.fread -@ cdecl free(ptr) msvcrt.free -@ cdecl freopen(str str ptr) msvcrt.freopen -@ cdecl frexp(double ptr) msvcrt.frexp -@ varargs fscanf(ptr str) msvcrt.fscanf -@ cdecl fseek(ptr long long) msvcrt.fseek -@ cdecl fsetpos(ptr ptr) msvcrt.fsetpos -@ cdecl ftell(ptr) msvcrt.ftell -@ varargs fwprintf(ptr wstr) msvcrt.fwprintf -@ cdecl fwrite(ptr long long ptr) msvcrt.fwrite -@ varargs fwscanf(ptr wstr) msvcrt.fwscanf -@ cdecl getc(ptr) msvcrt.getc -@ cdecl getchar() msvcrt.getchar -@ cdecl getenv(str) msvcrt.getenv -@ cdecl gets(str) msvcrt.gets -@ cdecl getwc(ptr) msvcrt.getwc -@ cdecl getwchar() msvcrt.getwchar -@ cdecl gmtime(ptr) msvcrt.gmtime -@ cdecl is_wctype(long long) msvcrt.is_wctype -@ cdecl isalnum(long) msvcrt.isalnum -@ cdecl isalpha(long) msvcrt.isalpha -@ cdecl iscntrl(long) msvcrt.iscntrl -@ cdecl isdigit(long) msvcrt.isdigit -@ cdecl isgraph(long) msvcrt.isgraph -@ cdecl isleadbyte(long) msvcrt.isleadbyte -@ cdecl islower(long) msvcrt.islower -@ cdecl isprint(long) msvcrt.isprint -@ cdecl ispunct(long) msvcrt.ispunct -@ cdecl isspace(long) msvcrt.isspace -@ cdecl isupper(long) msvcrt.isupper -@ cdecl iswalnum(long) msvcrt.iswalnum -@ cdecl iswalpha(long) msvcrt.iswalpha -@ cdecl iswascii(long) msvcrt.iswascii -@ cdecl iswcntrl(long) msvcrt.iswcntrl -@ cdecl iswctype(long long) msvcrt.iswctype -@ cdecl iswdigit(long) msvcrt.iswdigit -@ cdecl iswgraph(long) msvcrt.iswgraph -@ cdecl iswlower(long) msvcrt.iswlower -@ cdecl iswprint(long) msvcrt.iswprint -@ cdecl iswpunct(long) msvcrt.iswpunct -@ cdecl iswspace(long) msvcrt.iswspace -@ cdecl iswupper(long) msvcrt.iswupper -@ cdecl iswxdigit(long) msvcrt.iswxdigit -@ cdecl isxdigit(long) msvcrt.isxdigit -@ cdecl labs(long) msvcrt.labs -@ cdecl ldexp( double long) msvcrt.ldexp -@ cdecl ldiv(long long) msvcrt.ldiv -@ cdecl localeconv() msvcrt.localeconv -@ cdecl localtime(ptr) msvcrt.localtime -@ cdecl log(double) msvcrt.log -@ cdecl log10(double) msvcrt.log10 -@ cdecl -i386 longjmp(ptr long) msvcrt.longjmp -@ cdecl malloc(long) msvcrt.malloc -@ cdecl mblen(ptr long) msvcrt.mblen -@ cdecl mbstowcs(ptr str long) msvcrt.mbstowcs -@ cdecl mbtowc(wstr str long) msvcrt.mbtowc -@ cdecl memchr(ptr long long) msvcrt.memchr -@ cdecl memcmp(ptr ptr long) msvcrt.memcmp -@ cdecl memcpy(ptr ptr long) msvcrt.memcpy -@ cdecl memmove(ptr ptr long) msvcrt.memmove -@ cdecl memset(ptr long long) msvcrt.memset -@ cdecl mktime(ptr) msvcrt.mktime -@ cdecl modf(double ptr) msvcrt.modf -@ cdecl perror(str) msvcrt.perror -@ cdecl pow(double double) msvcrt.pow -@ varargs printf(str) msvcrt.printf -@ cdecl putc(long ptr) msvcrt.putc -@ cdecl putchar(long) msvcrt.putchar -@ cdecl puts(str) msvcrt.puts -@ cdecl putwc(long ptr) msvcrt.putwc -@ cdecl putwchar(long) msvcrt.putwchar -@ cdecl qsort(ptr long long ptr) msvcrt.qsort -@ cdecl raise(long) msvcrt.raise -@ cdecl rand() msvcrt.rand -@ cdecl realloc(ptr long) msvcrt.realloc -@ cdecl remove(str) msvcrt.remove -@ cdecl rename(str str) msvcrt.rename -@ cdecl rewind(ptr) msvcrt.rewind -@ varargs scanf(str) msvcrt.scanf -@ cdecl setbuf(ptr ptr) msvcrt.setbuf -@ cdecl setlocale(long str) msvcrt.setlocale -@ cdecl setvbuf(ptr str long long) msvcrt.setvbuf -@ cdecl signal(long long) msvcrt.signal -@ cdecl sin(double) msvcrt.sin -@ cdecl sinh(double) msvcrt.sinh -@ varargs sprintf(ptr str) msvcrt.sprintf -@ cdecl sqrt(double) msvcrt.sqrt -@ cdecl srand(long) msvcrt.srand -@ varargs sscanf(str str) msvcrt.sscanf -@ cdecl strcat(str str) msvcrt.strcat -@ cdecl strchr(str long) msvcrt.strchr -@ cdecl strcmp(str str) msvcrt.strcmp -@ cdecl strcoll(str str) msvcrt.strcoll -@ cdecl strcpy(ptr str) msvcrt.strcpy -@ cdecl strcspn(str str) msvcrt.strcspn -@ cdecl strerror(long) msvcrt.strerror -@ cdecl strftime(str long str ptr) msvcrt.strftime -@ cdecl strlen(str) msvcrt.strlen -@ cdecl strncat(str str long) msvcrt.strncat -@ cdecl strncmp(str str long) msvcrt.strncmp -@ cdecl strncpy(ptr str long) msvcrt.strncpy -@ cdecl strpbrk(str str) msvcrt.strpbrk -@ cdecl strrchr(str long) msvcrt.strrchr -@ cdecl strspn(str str) msvcrt.strspn -@ cdecl strstr(str str) msvcrt.strstr -@ cdecl strtod(str ptr) msvcrt.strtod -@ cdecl strtok(str str) msvcrt.strtok -@ cdecl strtol(str ptr long) msvcrt.strtol -@ cdecl strtoul(str ptr long) msvcrt.strtoul -@ cdecl strxfrm(ptr str long) msvcrt.strxfrm -@ varargs swprintf(wstr wstr) msvcrt.swprintf -@ varargs swscanf(wstr wstr) msvcrt.swscanf -@ cdecl system(str) msvcrt.system -@ cdecl tan(double) msvcrt.tan -@ cdecl tanh(double) msvcrt.tanh -@ cdecl time(ptr) msvcrt.time -@ cdecl tmpfile() msvcrt.tmpfile -@ cdecl tmpnam(ptr) msvcrt.tmpnam -@ cdecl tolower(long) msvcrt.tolower -@ cdecl toupper(long) msvcrt.toupper -@ cdecl towlower(long) msvcrt.towlower -@ cdecl towupper(long) msvcrt.towupper -@ cdecl ungetc(long ptr) msvcrt.ungetc -@ cdecl ungetwc(long ptr) msvcrt.ungetwc -@ cdecl vfprintf(ptr str long) msvcrt.vfprintf -@ cdecl vfwprintf(ptr wstr long) msvcrt.vfwprintf -@ cdecl vprintf(str long) msvcrt.vprintf -@ cdecl vsprintf(ptr str ptr) msvcrt.vsprintf -@ cdecl vswprintf(ptr wstr long) msvcrt.vswprintf -@ cdecl vwprintf(wstr long) msvcrt.vwprintf -@ cdecl wcscat(wstr wstr) msvcrt.wcscat -@ cdecl wcschr(wstr long) msvcrt.wcschr -@ cdecl wcscmp(wstr wstr) msvcrt.wcscmp -@ cdecl wcscoll(wstr wstr) msvcrt.wcscoll -@ cdecl wcscpy(ptr wstr) msvcrt.wcscpy -@ cdecl wcscspn(wstr wstr) msvcrt.wcscspn -@ cdecl wcsftime(ptr long wstr ptr) msvcrt.wcsftime -@ cdecl wcslen(wstr) msvcrt.wcslen -@ cdecl wcsncat(wstr wstr long) msvcrt.wcsncat -@ cdecl wcsncmp(wstr wstr long) msvcrt.wcsncmp -@ cdecl wcsncpy(ptr wstr long) msvcrt.wcsncpy -@ cdecl wcspbrk(wstr wstr) msvcrt.wcspbrk -@ cdecl wcsrchr(wstr long) msvcrt.wcsrchr -@ cdecl wcsspn(wstr wstr) msvcrt.wcsspn -@ cdecl wcsstr(wstr wstr) msvcrt.wcsstr -@ cdecl wcstod(wstr ptr) msvcrt.wcstod -@ cdecl wcstok(wstr wstr) msvcrt.wcstok -@ cdecl wcstol(wstr ptr long) msvcrt.wcstol -@ cdecl wcstombs(ptr ptr long) msvcrt.wcstombs -@ cdecl wcstoul(wstr ptr long) msvcrt.wcstoul -@ cdecl wcsxfrm(ptr wstr long) msvcrt.wcsxfrm -@ cdecl wctomb(ptr long) msvcrt.wctomb -@ varargs wprintf(wstr) msvcrt.wprintf -@ varargs wscanf(wstr) msvcrt.wscanf +@ cdecl _nextafter(double double) +@ cdecl _onexit(ptr) +@ varargs _open(str long) +@ cdecl _open_osfhandle(long long) +@ extern _osver +@ cdecl _pclose(ptr) +@ extern _pctype +@ extern _pgmptr +@ cdecl _pipe(ptr long long) +@ cdecl _popen(str str) +@ cdecl _purecall() +@ cdecl _putch(long) +@ cdecl _putenv(str) +@ cdecl _putw(long ptr) +@ cdecl _putws(wstr) +@ extern _pwctype +@ cdecl _read(long ptr long) +@ cdecl _rmdir(str) +@ cdecl _rmtmp() +@ cdecl _rotl(long long) +@ cdecl _rotr(long long) +@ cdecl _safe_fdiv() +@ cdecl _safe_fdivr() +@ cdecl _safe_fprem() +@ cdecl _safe_fprem1() +@ cdecl _scalb(double long) +@ cdecl _searchenv(str str ptr) +@ stdcall -i386 __seh_longjmp_unwind@4(ptr) _seh_longjmp_unwind +@ cdecl _seterrormode(long) +@ cdecl -i386 _setjmp(ptr) +@ cdecl -i386 _setjmp3(ptr long) +@ cdecl _setmbcp(long) +@ cdecl _setmode(long long) +@ cdecl _setsystime(ptr long) +@ cdecl _sleep(long) +@ varargs _snprintf(ptr long str) +@ varargs _snwprintf(ptr long wstr) +@ varargs _sopen(str long long) +@ varargs _spawnl(long str str) +@ varargs _spawnle(long str str) +@ varargs _spawnlp(long str str) +@ varargs _spawnlpe(long str str) +@ cdecl _spawnv(long str ptr) +@ cdecl _spawnve(long str ptr ptr) +@ cdecl _spawnvp(long str ptr) +@ cdecl _spawnvpe(long str ptr ptr) +@ cdecl _splitpath(str ptr ptr ptr ptr) +@ cdecl _stat(str ptr) +@ cdecl _statusfp() +@ cdecl _strcmpi(str str) +@ cdecl _strdate(ptr) +@ cdecl _strdup(str) +@ cdecl _strerror(long) +@ cdecl _stricmp(str str) +@ cdecl _stricoll(str str) +@ cdecl _strlwr(str) +@ cdecl _strncoll(str str long) +@ cdecl _strnicmp(str str long) +@ cdecl _strnicoll(str str long) +@ cdecl _strnset(str long long) +@ cdecl _strrev(str) +@ cdecl _strset(str long) +@ cdecl _strtime(ptr) +@ cdecl _strupr(str) +@ cdecl _swab(str str long) +@ extern _sys_errlist +@ extern _sys_nerr +@ cdecl _tccpy(str str) _mbccpy +@ cdecl _tclen(ptr) _mbclen +@ cdecl _tcschr(str long) _mbschr +@ cdecl _tcsclen(str) _mbslen +@ cdecl _tcscmp(str str) _mbscmp +@ cdecl _tcscspn(str str) _mbscspn +@ cdecl _tcsdec(ptr ptr) _mbsdec +@ cdecl _tcsicmp(str str) _mbsicmp +@ cdecl _tcsinc(str) _mbsinc +@ cdecl _tcslwr(str) _mbslwr +@ cdecl _tcsnbcnt(ptr long) _mbsnbcnt +@ cdecl _tcsncat(str str long) _mbsnbcat +@ cdecl _tcsnccat(str str long) _mbsncat +@ cdecl _tcsnccmp(str str long) _mbsncmp +@ cdecl _tcsnccnt(str long) _mbsnccnt +@ cdecl _tcsnccpy(str str long) _mbsncpy +@ cdecl _tcsncicmp(str str long) _mbsnicmp +@ cdecl _tcsncmp(str str long) _mbsnbcmp +@ cdecl _tcsncpy(ptr str long) _mbsnbcpy +@ cdecl _tcsncset(str long long) _mbsnset +@ cdecl _tcsnextc(str) _mbsnextc +@ cdecl _tcsnicmp(str str long) _mbsnbicmp +@ cdecl _tcsninc(str long) _mbsninc +@ cdecl _tcsnset(str long long) _mbsnbset +@ cdecl _tcspbrk(str str) _mbspbrk +@ cdecl _tcsrchr(str long) _mbsrchr +@ cdecl _tcsrev(str) _mbsrev +@ cdecl _tcsset(str long) _mbsset +@ cdecl _tcsspn(str str) _mbsspn +@ cdecl _tcsspnp(str str) _mbsspnp +@ cdecl _tcsstr(str str) _mbsstr +@ cdecl _tcstok(str str) _mbstok +@ cdecl _tcsupr(str) _mbsupr +@ cdecl _tell(long) +@ cdecl _tempnam(str str) +@ extern _timezone +@ cdecl _tolower(long) +@ cdecl _toupper(long) +@ extern _tzname +@ cdecl _tzset() +@ cdecl _ultoa(long ptr long) +@ cdecl _ultow(long ptr long) +@ cdecl _umask(long) +@ cdecl _ungetch(long) +@ cdecl _unlink(str) +@ cdecl _unloaddll(long) +@ cdecl _utime(str ptr) +@ cdecl _vsnprintf(ptr long ptr ptr) +@ cdecl _vsnwprintf(ptr long wstr long) +@ cdecl _waccess(wstr long) +@ cdecl _wasctime(ptr) +@ cdecl _wchdir(wstr) +@ cdecl _wchmod(wstr long) +@ extern _wcmdln +@ cdecl _wcreat(wstr long) +@ cdecl _wcsdup(wstr) +@ cdecl _wcsicmp(wstr wstr) +@ cdecl _wcsicoll(wstr wstr) +@ cdecl _wcslwr(wstr) +@ cdecl _wcsncoll(wstr wstr long) +@ cdecl _wcsnicmp(wstr wstr long) +@ cdecl _wcsnicoll(wstr wstr long) +@ cdecl _wcsnset(wstr long long) +@ cdecl _wcsrev(wstr) +@ cdecl _wcsset(wstr long) +@ cdecl _wcsupr(wstr) +@ cdecl _wctime(ptr) +@ extern _wenviron +@ varargs _wexecl(wstr wstr) +@ varargs _wexecle(wstr wstr) +@ varargs _wexeclp(wstr wstr) +@ varargs _wexeclpe(wstr wstr) +@ varargs _wexecv(wstr ptr) +@ varargs _wexecve(wstr ptr ptr) +@ varargs _wexecvp(wstr ptr) +@ varargs _wexecvpe(wstr ptr ptr) +@ cdecl _wfdopen(long wstr) +@ cdecl _wfindfirst(wstr ptr) +@ cdecl _wfindnext(long ptr) +@ cdecl _wfopen(wstr wstr) +@ cdecl _wfreopen(wstr wstr ptr) +@ cdecl _wfsopen(wstr wstr long) +@ cdecl _wfullpath(ptr wstr long) +@ cdecl _wgetcwd(wstr long) +@ cdecl _wgetdcwd(long wstr long) +@ cdecl _wgetenv(wstr) +@ extern _winmajor +@ extern _winminor +@ extern _winver +@ cdecl _wmakepath(ptr wstr wstr wstr wstr) +@ cdecl _wmkdir(wstr) +@ cdecl _wmktemp(wstr) +@ varargs _wopen(wstr long) +@ cdecl _wperror(wstr) +@ extern _wpgmptr +@ cdecl _wpopen(wstr wstr) +@ cdecl _wputenv(wstr) +@ cdecl _wremove(wstr) +@ cdecl _wrename(wstr wstr) +@ cdecl _write(long ptr long) +@ cdecl _wrmdir(wstr) +@ cdecl _wsearchenv(wstr wstr ptr) +@ cdecl _wsetlocale(long wstr) +@ varargs _wsopen(wstr long long) +@ varargs _wspawnl(long wstr wstr) +@ varargs _wspawnle(long wstr wstr) +@ varargs _wspawnlp(long wstr wstr) +@ varargs _wspawnlpe(long wstr wstr) +@ cdecl _wspawnv(long wstr ptr) +@ cdecl _wspawnve(long wstr ptr ptr) +@ cdecl _wspawnvp(long wstr ptr) +@ cdecl _wspawnvpe(long wstr ptr ptr) +@ cdecl _wsplitpath(wstr ptr ptr ptr ptr) +@ cdecl _wstat(wstr ptr) +@ cdecl _wstrdate(ptr) +@ cdecl _wstrtime(ptr) +@ cdecl _wsystem(wstr) +@ cdecl _wtempnam(wstr wstr) +@ cdecl _wtmpnam(ptr) +@ cdecl _wtoi(wstr) +@ cdecl _wtol(wstr) +@ cdecl _wunlink(wstr) +@ cdecl _wutime(wstr ptr) +@ cdecl _y0(double) +@ cdecl _y1(double) +@ cdecl _yn(long double ) +@ cdecl abort() +@ cdecl abs(long) +@ cdecl acos(double) +@ cdecl asctime(ptr) +@ cdecl asin(double) +@ cdecl atan(double) +@ cdecl atan2(double double) +@ extern atexit # <-- do not touch this! +@ cdecl atof(str) +@ cdecl atoi(str) +@ cdecl atol(str) +@ cdecl bsearch(ptr ptr long long ptr) +@ cdecl calloc(long long) +@ cdecl ceil(double) +@ cdecl clearerr(ptr) +@ cdecl clock() +@ cdecl cos(double) +@ cdecl cosh(double) +@ cdecl ctime(ptr) +@ cdecl difftime(long long) +@ cdecl div(long long) +@ cdecl exit(long) +@ cdecl exp(double) +@ cdecl fabs(double) +@ cdecl fclose(ptr) +@ cdecl feof(ptr) +@ cdecl ferror(ptr) +@ cdecl fflush(ptr) +@ cdecl fgetc(ptr) +@ cdecl fgetpos(ptr ptr) +@ cdecl fgets(ptr long ptr) +@ cdecl fgetwc(ptr) +@ cdecl fgetws(ptr long ptr) +@ cdecl floor(double) +@ cdecl fmod(double double) +@ cdecl fopen(str str) +@ varargs fprintf(ptr str) +@ cdecl fputc(long ptr) +@ cdecl fputs(str ptr) +@ cdecl fputwc(long ptr) +@ cdecl fputws(wstr ptr) +@ cdecl fread(ptr long long ptr) +@ cdecl free(ptr) +@ cdecl freopen(str str ptr) +@ cdecl frexp(double ptr) +@ varargs fscanf(ptr str) +@ cdecl fseek(ptr long long) +@ cdecl fsetpos(ptr ptr) +@ cdecl ftell(ptr) +@ varargs fwprintf(ptr wstr) +@ cdecl fwrite(ptr long long ptr) +@ varargs fwscanf(ptr wstr) +@ cdecl getc(ptr) +@ cdecl getchar() +@ cdecl getenv(str) +@ cdecl gets(str) +@ cdecl getwc(ptr) +@ cdecl getwchar() +@ cdecl gmtime(ptr) +@ cdecl is_wctype(long long) +@ cdecl isalnum(long) +@ cdecl isalpha(long) +@ cdecl iscntrl(long) +@ cdecl isdigit(long) +@ cdecl isgraph(long) +@ cdecl isleadbyte(long) +@ cdecl islower(long) +@ cdecl isprint(long) +@ cdecl ispunct(long) +@ cdecl isspace(long) +@ cdecl isupper(long) +@ cdecl iswalnum(long) +@ cdecl iswalpha(long) +@ cdecl iswascii(long) +@ cdecl iswcntrl(long) +@ cdecl iswctype(long long) +@ cdecl iswdigit(long) +@ cdecl iswgraph(long) +@ cdecl iswlower(long) +@ cdecl iswprint(long) +@ cdecl iswpunct(long) +@ cdecl iswspace(long) +@ cdecl iswupper(long) +@ cdecl iswxdigit(long) +@ cdecl isxdigit(long) +@ cdecl labs(long) +@ cdecl ldexp(double long) +@ cdecl ldiv(long long) +@ cdecl localeconv() +@ cdecl localtime(ptr) +@ cdecl log(double) +@ cdecl log10(double) +@ cdecl -i386 longjmp(ptr long) +@ cdecl malloc(long) +@ cdecl mblen(ptr long) +@ cdecl mbstowcs(ptr str long) +@ cdecl mbtowc(wstr str long) +@ cdecl memchr(ptr long long) +@ cdecl memcmp(ptr ptr long) +@ cdecl memcpy(ptr ptr long) +@ cdecl memmove(ptr ptr long) +@ cdecl memset(ptr long long) +@ cdecl mktime(ptr) +@ cdecl modf(double ptr) +@ cdecl perror(str) +@ cdecl pow(double double) +@ varargs printf(str) +@ cdecl putc(long ptr) +@ cdecl putchar(long) +@ cdecl puts(str) +@ cdecl putwc(long ptr) fputwc +@ cdecl putwchar(long) _fputwchar +@ cdecl qsort(ptr long long ptr) +@ cdecl raise(long) +@ cdecl rand() +@ cdecl realloc(ptr long) +@ cdecl remove(str) +@ cdecl rename(str str) +@ cdecl rewind(ptr) +@ varargs scanf(str) +@ cdecl setbuf(ptr ptr) +@ cdecl setlocale(long str) +@ cdecl setvbuf(ptr str long long) +@ cdecl signal(long long) +@ cdecl sin(double) +@ cdecl sinh(double) +@ varargs sprintf(ptr str) +@ cdecl sqrt(double) +@ cdecl srand(long) +@ varargs sscanf(str str) +@ cdecl strcat(str str) +@ cdecl strchr(str long) +@ cdecl strcmp(str str) +@ cdecl strcoll(str str) +@ cdecl strcpy(ptr str) +@ cdecl strcspn(str str) +@ cdecl strerror(long) +@ cdecl strftime(str long str ptr) +@ cdecl strlen(str) +@ cdecl strncat(str str long) +@ cdecl strncmp(str str long) +@ cdecl strncpy(ptr str long) +@ cdecl strpbrk(str str) +@ cdecl strrchr(str long) +@ cdecl strspn(str str) +@ cdecl strstr(str str) +@ cdecl strtod(str ptr) +@ cdecl strtok(str str) +@ cdecl strtol(str ptr long) +@ cdecl strtoul(str ptr long) +@ cdecl strxfrm(ptr str long) +@ varargs swprintf(ptr wstr) +@ varargs swscanf(wstr wstr) +@ cdecl system(str) +@ cdecl tan(double) +@ cdecl tanh(double) +@ cdecl time(ptr) +@ cdecl tmpfile() +@ cdecl tmpnam(ptr) +@ cdecl tolower(long) +@ cdecl toupper(long) +@ cdecl towlower(long) +@ cdecl towupper(long) +@ cdecl ungetc(long ptr) +@ cdecl ungetwc(long ptr) +@ cdecl vfprintf(ptr str ptr) +@ cdecl vfwprintf(ptr wstr ptr) +@ cdecl vprintf(str ptr) +@ cdecl vsprintf(ptr str ptr) +@ cdecl vswprintf(ptr wstr long) +@ cdecl vwprintf(wstr long) +@ cdecl wcscat(wstr wstr) +@ cdecl wcschr(wstr long) +@ cdecl wcscmp(wstr wstr) +@ cdecl wcscoll(wstr wstr) +@ cdecl wcscpy(ptr wstr) +@ cdecl wcscspn(wstr wstr) +@ cdecl wcsftime(ptr long wstr ptr) +@ cdecl wcslen(wstr) +@ cdecl wcsncat(wstr wstr long) +@ cdecl wcsncmp(wstr wstr long) +@ cdecl wcsncpy(ptr wstr long) +@ cdecl wcspbrk(wstr wstr) +@ cdecl wcsrchr(wstr long) +@ cdecl wcsspn(wstr wstr) +@ cdecl wcsstr(wstr wstr) +@ cdecl wcstod(wstr ptr) +@ cdecl wcstok(wstr wstr) +@ cdecl wcstol(wstr ptr long) +@ cdecl wcstombs(ptr ptr long) +@ cdecl wcstoul(wstr ptr long) +@ cdecl wcsxfrm(ptr wstr long) +@ cdecl wctomb(ptr long) +@ varargs wprintf(wstr) +@ varargs wscanf(wstr) diff --git a/dll/win32/msvcrt20/stubs.c b/dll/win32/msvcrt20/stubs.c new file mode 100644 index 00000000000..489e122ef4f --- /dev/null +++ b/dll/win32/msvcrt20/stubs.c @@ -0,0 +1,27 @@ +#include + +#undef UNIMPLEMENTED +#define UNIMPLEMENTED __wine_spec_unimplemented_stub("msvcrt.dll", __FUNCTION__) + +int _atodbl( + void * value, + char * str) +{ + UNIMPLEMENTED; + return 0; +} + +int _ismbbkprint( + unsigned int c) +{ + UNIMPLEMENTED; + return 0; +} + +size_t _heapused( size_t *pUsed, size_t *pCommit ) +{ + UNIMPLEMENTED; + return( 0 ); +} + +int _fileinfo = 0; \ No newline at end of file diff --git a/dll/win32/msvcrt40/CMakeLists.txt b/dll/win32/msvcrt40/CMakeLists.txt index ac69cb56d38..747351d74f0 100644 --- a/dll/win32/msvcrt40/CMakeLists.txt +++ b/dll/win32/msvcrt40/CMakeLists.txt @@ -1,21 +1,34 @@ -include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) - -add_definitions(-D__WINESRC__) -add_definitions(-DCRTDLL) +add_definitions( + -DUSE_MSVCRT_PREFIX + -D_MSVCRT_ + -D_MSVCRT_LIB_ + -D_MT + -D_CTYPE_DISABLE_MACROS + -D_NO_INLINING + -DCRTDLL + -D__MINGW_IMPORT="") + +include_directories(${REACTOS_SOURCE_DIR}/lib/sdk/crt/include) spec2def(msvcrt40.dll msvcrt40.spec) list(APPEND SOURCE msvcrt40.c + stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/msvcrt40_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/msvcrt40.def) add_library(msvcrt40 SHARED ${SOURCE}) +set_image_base(msvcrt40 ${baseaddress_msvcrt40}) +set_entrypoint(msvcrt40 DllMain@12) -set_module_type(msvcrt40 win32dll) +target_link_libraries(msvcrt40 crt wine) -target_link_libraries(msvcrt40 wine) +if(NOT MSVC) + target_link_libraries(msvcrt40 pseh) +endif() -add_importlibs(msvcrt40 msvcrt kernel32 ntdll) +add_importlibs(msvcrt40 kernel32 ntdll) add_cd_file(TARGET msvcrt40 DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/msvcrt40/msvcrt40.c b/dll/win32/msvcrt40/msvcrt40.c index f178ea0bafa..fdd7457d087 100644 --- a/dll/win32/msvcrt40/msvcrt40.c +++ b/dll/win32/msvcrt40/msvcrt40.c @@ -17,23 +17,136 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + +#include +#define _CRT_PRECOMP_H +#include +#include +#include +#include +#include +#include -#include +#include "wine/debug.h" +WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); -#include "windef.h" -#include "winbase.h" +/* EXTERNAL PROTOTYPES ********************************************************/ -BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) +extern int BlockEnvToEnvironA(void); +extern int BlockEnvToEnvironW(void); +extern void FreeEnvironment(char **environment); +extern void _atexit_cleanup(void); + +extern unsigned int _osplatform; +extern unsigned int _osver; +extern unsigned int _winminor; +extern unsigned int _winmajor; +extern unsigned int _winver; + +extern char* _acmdln; /* pointer to ascii command line */ +extern wchar_t* _wcmdln; /* pointer to wide character command line */ +#undef _environ +extern char** _environ; /* pointer to environment block */ +extern char** __initenv; /* pointer to initial environment block */ +extern wchar_t** _wenviron; /* pointer to environment block */ +extern wchar_t** __winitenv; /* pointer to initial environment block */ + + +/* LIBRARY GLOBAL VARIABLES ***************************************************/ + +HANDLE hHeap = NULL; /* handle for heap */ + + +/* LIBRARY ENTRY POINT ********************************************************/ + +BOOL +WINAPI +DllMain(PVOID hinstDll, ULONG dwReason, PVOID reserved) { - switch (reason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls( inst ); - break; + OSVERSIONINFOW osvi; + switch (dwReason) + { + case DLL_PROCESS_ATTACH://1 + /* initialize version info */ + //DPRINT1("Process Attach %d\n", nAttachCount); + //DPRINT1("Process Attach\n"); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + GetVersionExW( &osvi ); + _winver = (osvi.dwMajorVersion << 8) | osvi.dwMinorVersion; + _winmajor = osvi.dwMajorVersion; + _winminor = osvi.dwMinorVersion; + _osplatform = osvi.dwPlatformId; + _osver = osvi.dwBuildNumber; + hHeap = HeapCreate(0, 100000, 0); + if (hHeap == NULL) + return FALSE; + + /* create tls stuff */ + if (!CreateThreadData()) + return FALSE; + + if (BlockEnvToEnvironA() < 0) + return FALSE; + + if (BlockEnvToEnvironW() < 0) + { + FreeEnvironment(_environ); + return FALSE; + } + + _acmdln = _strdup(GetCommandLineA()); + _wcmdln = _wcsdup(GetCommandLineW()); + + /* FIXME: more initializations... */ + + /* Initialization of the WINE code */ + msvcrt_init_mt_locks(); + msvcrt_init_io(); + setlocale(0, "C"); + //_setmbcp(_MB_CP_LOCALE); + + TRACE("Attach done\n"); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + FreeThreadData(NULL); + break; + case DLL_PROCESS_DETACH: + //DPRINT1("Detach %d\n", nAttachCount); + //DPRINT("Detach\n"); + /* FIXME: more cleanup... */ + /* Deinit of the WINE code */ + msvcrt_free_io(); + msvcrt_free_mt_locks(); + + _atexit_cleanup(); + + + /* destroy tls stuff */ + DestroyThreadData(); + + if (__winitenv && __winitenv != _wenviron) + FreeEnvironment((char**)__winitenv); + if (_wenviron) + FreeEnvironment((char**)_wenviron); + + if (__initenv && __initenv != _environ) + FreeEnvironment(__initenv); + if (_environ) + FreeEnvironment(_environ); + + /* destroy heap */ + HeapDestroy(hHeap); + + TRACE("Detach done\n"); break; - } - return TRUE; + } + + return TRUE; } + +/* EOF */ \ No newline at end of file diff --git a/dll/win32/msvcrt40/msvcrt40.spec b/dll/win32/msvcrt40/msvcrt40.spec index 3e43afa908b..5383a360f80 100644 --- a/dll/win32/msvcrt40/msvcrt40.spec +++ b/dll/win32/msvcrt40/msvcrt40.spec @@ -1,14 +1,14 @@ @ stub ??0Iostream_init@@QAE@AAVios@@H@Z @ stub ??0Iostream_init@@QAE@XZ -@ cdecl -i386 ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) msvcrt.??0__non_rtti_object@@QAE@ABV0@@Z -@ cdecl -i386 ??0__non_rtti_object@@QAE@PBD@Z(ptr) msvcrt.??0__non_rtti_object@@QAE@PBD@Z -@ cdecl -i386 ??0bad_cast@@QAE@ABQBD@Z(ptr) msvcrt.??0bad_cast@@QAE@ABQBD@Z -@ cdecl -i386 ??0bad_cast@@QAE@ABV0@@Z(ptr) msvcrt.??0bad_cast@@QAE@ABV0@@Z -@ cdecl -i386 ??0bad_typeid@@QAE@ABV0@@Z(ptr) msvcrt.??0bad_typeid@@QAE@ABV0@@Z -@ cdecl -i386 ??0bad_typeid@@QAE@PBD@Z(ptr) msvcrt.??0bad_typeid@@QAE@PBD@Z -@ cdecl -i386 ??0exception@@QAE@ABQBD@Z(ptr) msvcrt.??0exception@@QAE@ABQBD@Z -@ cdecl -i386 ??0exception@@QAE@ABV0@@Z(ptr) msvcrt.??0exception@@QAE@ABV0@@Z -@ cdecl -i386 ??0exception@@QAE@XZ() msvcrt.??0exception@@QAE@XZ +@ cdecl -i386 ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_copy_ctor +@ cdecl -i386 ??0__non_rtti_object@@QAE@PBD@Z(ptr) __thiscall_MSVCRT___non_rtti_object_ctor +@ cdecl -i386 ??0bad_cast@@QAE@ABQBD@Z(ptr) __thiscall_MSVCRT_bad_cast_ctor +@ cdecl -i386 ??0bad_cast@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_cast_copy_ctor +@ cdecl -i386 ??0bad_typeid@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_typeid_copy_ctor +@ cdecl -i386 ??0bad_typeid@@QAE@PBD@Z(ptr) __thiscall_MSVCRT_bad_typeid_ctor +@ cdecl -i386 ??0exception@@QAE@ABQBD@Z(ptr) __thiscall_MSVCRT_exception_ctor +@ cdecl -i386 ??0exception@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT_exception_copy_ctor +@ cdecl -i386 ??0exception@@QAE@XZ() __thiscall_MSVCRT_exception_default_ctor @ stub ??0filebuf@@QAE@ABV0@@Z @ stub ??0filebuf@@QAE@H@Z @ stub ??0filebuf@@QAE@HPADH@Z @@ -70,10 +70,10 @@ @ stub ??0strstreambuf@@QAE@PADH0@Z @ stub ??0strstreambuf@@QAE@XZ @ stub ??1Iostream_init@@QAE@XZ -@ cdecl -i386 ??1__non_rtti_object@@UAE@XZ() msvcrt.??1__non_rtti_object@@UAE@XZ -@ cdecl -i386 ??1bad_cast@@UAE@XZ() msvcrt.??1bad_cast@@UAE@XZ -@ cdecl -i386 ??1bad_typeid@@UAE@XZ() msvcrt.??1bad_typeid@@UAE@XZ -@ cdecl -i386 ??1exception@@UAE@XZ() msvcrt.??1exception@@UAE@XZ +@ cdecl -i386 ??1__non_rtti_object@@UAE@XZ() __thiscall_MSVCRT___non_rtti_object_dtor +@ cdecl -i386 ??1bad_cast@@UAE@XZ() __thiscall_MSVCRT_bad_cast_dtor +@ cdecl -i386 ??1bad_typeid@@UAE@XZ() __thiscall_MSVCRT_bad_typeid_dtor +@ cdecl -i386 ??1exception@@UAE@XZ() __thiscall_MSVCRT_exception_dtor @ stub ??1filebuf@@UAE@XZ @ stub ??1fstream@@UAE@XZ @ stub ??1ifstream@@UAE@XZ @@ -92,14 +92,14 @@ @ stub ??1streambuf@@UAE@XZ @ stub ??1strstream@@UAE@XZ @ stub ??1strstreambuf@@UAE@XZ -@ cdecl -i386 ??1type_info@@UAE@XZ() msvcrt.??1type_info@@UAE@XZ -@ cdecl ??2@YAPAXI@Z(long) msvcrt.??2@YAPAXI@Z -@ cdecl ??3@YAXPAX@Z(ptr) msvcrt.??3@YAXPAX@Z +@ cdecl -i386 ??1type_info@@UAE@XZ() __thiscall_MSVCRT_type_info_dtor +@ cdecl ??2@YAPAXI@Z(long) MSVCRT_operator_new +@ cdecl ??3@YAXPAX@Z(ptr) MSVCRT_operator_delete @ stub ??4Iostream_init@@QAEAAV0@ABV0@@Z -@ cdecl -i386 ??4__non_rtti_object@@QAEAAV0@ABV0@@Z(ptr) msvcrt.??4__non_rtti_object@@QAEAAV0@ABV0@@Z -@ cdecl -i386 ??4bad_cast@@QAEAAV0@ABV0@@Z(ptr) msvcrt.??4bad_cast@@QAEAAV0@ABV0@@Z -@ cdecl -i386 ??4bad_typeid@@QAEAAV0@ABV0@@Z(ptr) msvcrt.??4bad_typeid@@QAEAAV0@ABV0@@Z -@ cdecl -i386 ??4exception@@QAEAAV0@ABV0@@Z(ptr) msvcrt.??4exception@@QAEAAV0@ABV0@@Z +@ cdecl -i386 ??4__non_rtti_object@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_opequals +@ cdecl -i386 ??4bad_cast@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_cast_opequals +@ cdecl -i386 ??4bad_typeid@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_bad_typeid_opequals +@ cdecl -i386 ??4exception@@QAEAAV0@ABV0@@Z(ptr) __thiscall_MSVCRT_exception_opequals @ stub ??4filebuf@@QAEAAV0@ABV0@@Z @ stub ??4fstream@@QAEAAV0@AAV0@@Z @ stub ??4ifstream@@QAEAAV0@ABV0@@Z @@ -163,13 +163,13 @@ @ stub ??6ostream@@QAEAAV0@PBE@Z @ stub ??6ostream@@QAEAAV0@PBX@Z @ stub ??7ios@@QBEHXZ -@ cdecl -i386 ??8type_info@@QBEHABV0@@Z(ptr) msvcrt.??8type_info@@QBEHABV0@@Z -@ cdecl -i386 ??9type_info@@QBEHABV0@@Z(ptr) msvcrt.??9type_info@@QBEHABV0@@Z +@ cdecl -i386 ??8type_info@@QBEHABV0@@Z(ptr) __thiscall_MSVCRT_type_info_opequals_equals +@ cdecl -i386 ??9type_info@@QBEHABV0@@Z(ptr) __thiscall_MSVCRT_type_info_opnot_equals @ stub ??Bios@@QBEPAXXZ -@ extern -i386 ??_7__non_rtti_object@@6B@ msvcrt.??_7__non_rtti_object@@6B@ -@ extern -i386 ??_7bad_cast@@6B@ msvcrt.??_7bad_cast@@6B@ -@ extern -i386 ??_7bad_typeid@@6B@ msvcrt.??_7bad_typeid@@6B@ -@ extern -i386 ??_7exception@@6B@ msvcrt.??_7exception@@6B@ +@ extern -i386 ??_7__non_rtti_object@@6B@ MSVCRT___non_rtti_object_vtable +@ extern -i386 ??_7bad_cast@@6B@ MSVCRT_bad_cast_vtable +@ extern -i386 ??_7bad_typeid@@6B@ MSVCRT_bad_typeid_vtable +@ extern -i386 ??_7exception@@6B@ MSVCRT_exception_vtable @ stub ??_7filebuf@@6B@ @ stub ??_7fstream@@6B@ @ stub ??_7ifstream@@6B@ @@ -217,10 +217,10 @@ @ stub ??_Dstdiostream@@QAEXXZ @ stub ??_Dstrstream@@QAEXXZ @ stub ??_EIostream_init@@QAEPAXI@Z -@ cdecl -i386 ??_E__non_rtti_object@@UAEPAXI@Z(long) msvcrt.??_E__non_rtti_object@@UAEPAXI@Z -@ cdecl -i386 ??_Ebad_cast@@UAEPAXI@Z(long) msvcrt.??_Ebad_cast@@UAEPAXI@Z -@ cdecl -i386 ??_Ebad_typeid@@UAEPAXI@Z(long) msvcrt.??_Ebad_typeid@@UAEPAXI@Z -@ cdecl -i386 ??_Eexception@@UAEPAXI@Z(long) msvcrt.??_Eexception@@UAEPAXI@Z +@ cdecl -i386 ??_E__non_rtti_object@@UAEPAXI@Z(long) __thiscall_MSVCRT___non_rtti_object_vector_dtor +@ cdecl -i386 ??_Ebad_cast@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_cast_vector_dtor +@ cdecl -i386 ??_Ebad_typeid@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_typeid_vector_dtor +@ cdecl -i386 ??_Eexception@@UAEPAXI@Z(long) __thiscall_MSVCRT_exception_vector_dtor @ stub ??_Efilebuf@@UAEPAXI@Z @ stub ??_Efstream@@UAEPAXI@Z @ stub ??_Eifstream@@UAEPAXI@Z @@ -240,10 +240,10 @@ @ stub ??_Estrstream@@UAEPAXI@Z @ stub ??_Estrstreambuf@@UAEPAXI@Z @ stub ??_GIostream_init@@QAEPAXI@Z -@ cdecl -i386 ??_G__non_rtti_object@@UAEPAXI@Z(long) msvcrt.??_G__non_rtti_object@@UAEPAXI@Z -@ cdecl -i386 ??_Gbad_cast@@UAEPAXI@Z(long) msvcrt.??_Gbad_cast@@UAEPAXI@Z -@ cdecl -i386 ??_Gbad_typeid@@UAEPAXI@Z(long) msvcrt.??_Gbad_typeid@@UAEPAXI@Z -@ cdecl -i386 ??_Gexception@@UAEPAXI@Z(long) msvcrt.??_Gexception@@UAEPAXI@Z +@ cdecl -i386 ??_G__non_rtti_object@@UAEPAXI@Z(long) __thiscall_MSVCRT___non_rtti_object_scalar_dtor +@ cdecl -i386 ??_Gbad_cast@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_cast_scalar_dtor +@ cdecl -i386 ??_Gbad_typeid@@UAEPAXI@Z(long) __thiscall_MSVCRT_bad_typeid_scalar_dtor +@ cdecl -i386 ??_Gexception@@UAEPAXI@Z(long) __thiscall_MSVCRT_exception_scalar_dtor @ stub ??_Gfilebuf@@UAEPAXI@Z @ stub ??_Gfstream@@UAEPAXI@Z @ stub ??_Gifstream@@UAEPAXI@Z @@ -262,11 +262,11 @@ @ stub ??_Gstreambuf@@UAEPAXI@Z @ stub ??_Gstrstream@@UAEPAXI@Z @ stub ??_Gstrstreambuf@@UAEPAXI@Z -@ cdecl ?_query_new_handler@@YAP6AHI@ZXZ() msvcrt.?_query_new_handler@@YAP6AHI@ZXZ -@ cdecl ?_query_new_mode@@YAHXZ() msvcrt.?_query_new_mode@@YAHXZ -@ cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) msvcrt.?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z -@ cdecl ?_set_new_mode@@YAHH@Z(long) msvcrt.?_set_new_mode@@YAHH@Z -@ cdecl ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) msvcrt.?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z +@ cdecl ?_query_new_handler@@YAP6AHI@ZXZ() MSVCRT__query_new_handler +@ cdecl ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode +@ cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) MSVCRT__set_new_handler +@ cdecl ?_set_new_mode@@YAHH@Z(long) MSVCRT__set_new_mode +@ cdecl ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) MSVCRT__set_se_translator @ stub ?adjustfield@ios@@2JB @ stub ?allocate@streambuf@@IAEHXZ @ stub ?attach@filebuf@@QAEPAV1@H@Z @@ -276,7 +276,7 @@ @ stub ?bad@ios@@QBEHXZ @ stub ?base@streambuf@@IBEPADXZ @ stub ?basefield@ios@@2JB -@ cdecl -i386 ?before@type_info@@QBEHABV1@@Z(ptr) msvcrt.?before@type_info@@QBEHABV1@@Z +@ cdecl -i386 ?before@type_info@@QBEHABV1@@Z(ptr) __thiscall_MSVCRT_type_info_before @ stub ?binary@filebuf@@2HB @ stub ?bitalloc@ios@@SAJXZ @ stub ?blen@streambuf@@IBEHXZ @@ -354,7 +354,7 @@ @ stub ?lockc@ios@@KAXXZ @ stub ?lockptr@ios@@IAEPAU_CRT_CRITICAL_SECTION@@XZ @ stub ?lockptr@streambuf@@IAEPAU_CRT_CRITICAL_SECTION@@XZ -@ cdecl -i386 ?name@type_info@@QBEPBDXZ() msvcrt.?name@type_info@@QBEPBDXZ +@ cdecl -i386 ?name@type_info@@QBEPBDXZ() __thiscall_MSVCRT_type_info_name @ stub ?oct@@YAAAVios@@AAV1@@Z @ stub ?open@filebuf@@QAEPAV1@PBDHH@Z @ stub ?open@fstream@@QAEXPBDHH@Z @@ -382,7 +382,7 @@ @ stub ?put@ostream@@QAEAAV1@E@Z @ stub ?putback@istream@@QAEAAV1@D@Z @ stub ?pword@ios@@QBEAAPAXH@Z -@ cdecl -i386 ?raw_name@type_info@@QBEPBDXZ() msvcrt.?raw_name@type_info@@QBEPBDXZ +@ cdecl -i386 ?raw_name@type_info@@QBEPBDXZ() __thiscall_MSVCRT_type_info_raw_name @ stub ?rdbuf@fstream@@QBEPAVfilebuf@@XZ @ stub ?rdbuf@ifstream@@QBEPAVfilebuf@@XZ @ stub ?rdbuf@ios@@QBEPAVstreambuf@@XZ @@ -405,9 +405,9 @@ @ stub ?seekp@ostream@@QAEAAV1@J@Z @ stub ?seekp@ostream@@QAEAAV1@JW4seek_dir@ios@@@Z @ stub ?seekpos@streambuf@@UAEJJH@Z -@ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) msvcrt.?set_new_handler@@YAP6AXXZP6AXXZ@Z -@ cdecl ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) msvcrt.?set_terminate@@YAP6AXXZP6AXXZ@Z -@ cdecl ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) msvcrt.?set_unexpected@@YAP6AXXZP6AXXZ@Z +@ cdecl ?set_new_handler@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_new_handler +@ cdecl ?set_terminate@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_terminate +@ cdecl ?set_unexpected@@YAP6AXXZP6AXXZ@Z(ptr) MSVCRT_set_unexpected @ stub ?setb@streambuf@@IAEXPAD0H@Z @ stub ?setbuf@filebuf@@UAEPAVstreambuf@@PADH@Z @ stub ?setbuf@fstream@@QAEPAVstreambuf@@PADH@Z @@ -450,7 +450,7 @@ @ stub ?sync_with_stdio@ios@@SAXXZ @ stub ?tellg@istream@@QAEJXZ @ stub ?tellp@ostream@@QAEJXZ -@ cdecl ?terminate@@YAXXZ() msvcrt.?terminate@@YAXXZ +@ cdecl ?terminate@@YAXXZ() MSVCRT_terminate @ stub ?text@filebuf@@2HB @ stub ?tie@ios@@QAEPAVostream@@PAV2@@Z @ stub ?tie@ios@@QBEPAVostream@@XZ @@ -459,13 +459,13 @@ @ stub ?underflow@filebuf@@UAEHXZ @ stub ?underflow@stdiobuf@@UAEHXZ @ stub ?underflow@strstreambuf@@UAEHXZ -@ cdecl ?unexpected@@YAXXZ() msvcrt.?unexpected@@YAXXZ +@ cdecl ?unexpected@@YAXXZ() MSVCRT_unexpected @ stub ?unlock@ios@@QAAXXZ @ stub ?unlock@streambuf@@QAEXXZ @ stub ?unlockbuf@ios@@QAAXXZ @ stub ?unlockc@ios@@KAXXZ @ stub ?unsetf@ios@@QAEJJ@Z -@ cdecl -i386 ?what@exception@@UBEPBDXZ() msvcrt.?what@exception@@UBEPBDXZ +@ cdecl -i386 ?what@exception@@UBEPBDXZ() __thiscall_MSVCRT_what_exception @ stub ?width@ios@@QAEHH@Z @ stub ?width@ios@@QBEHXZ @ stub ?write@ostream@@QAEAAV1@PBCH@Z @@ -480,686 +480,686 @@ @ stub ?xalloc@ios@@SAHXZ @ stub ?xsgetn@streambuf@@UAEHPADH@Z @ stub ?xsputn@streambuf@@UAEHPBDH@Z -@ cdecl $I10_OUTPUT() msvcrt.$I10_OUTPUT -@ cdecl -arch=i386 _CIacos() msvcrt._CIacos -@ cdecl -arch=i386 _CIasin() msvcrt._CIasin -@ cdecl -arch=i386 _CIatan() msvcrt._CIatan -@ cdecl -arch=i386 _CIatan2() msvcrt._CIatan2 -@ cdecl -arch=i386 _CIcos() msvcrt._CIcos -@ cdecl -arch=i386 _CIcosh() msvcrt._CIcosh -@ cdecl -arch=i386 _CIexp() msvcrt._CIexp -@ cdecl -arch=i386 _CIfmod() msvcrt._CIfmod -@ cdecl -arch=i386 _CIlog() msvcrt._CIlog -@ cdecl -arch=i386 _CIlog10() msvcrt._CIlog10 -@ cdecl -arch=i386 _CIpow() msvcrt._CIpow -@ cdecl -arch=i386 _CIsin() msvcrt._CIsin -@ cdecl -arch=i386 _CIsinh() msvcrt._CIsinh -@ cdecl -arch=i386 _CIsqrt() msvcrt._CIsqrt -@ cdecl -arch=i386 _CItan() msvcrt._CItan -@ cdecl -arch=i386 _CItanh() msvcrt._CItanh -@ stdcall _CxxThrowException(long long) msvcrt._CxxThrowException -@ cdecl -i386 _EH_prolog() msvcrt._EH_prolog -@ extern _HUGE msvcrt._HUGE -@ cdecl _XcptFilter(long ptr) msvcrt._XcptFilter -@ cdecl -i386 __CxxFrameHandler(ptr ptr ptr ptr) msvcrt.__CxxFrameHandler -@ stdcall __CxxLongjmpUnwind(ptr) msvcrt.__CxxLongjmpUnwind -@ cdecl __RTCastToVoid(ptr) msvcrt.__RTCastToVoid -@ cdecl __RTDynamicCast(ptr long ptr ptr long) msvcrt.__RTDynamicCast -@ cdecl __RTtypeid(ptr) msvcrt.__RTtypeid -@ cdecl __STRINGTOLD(ptr ptr str long) msvcrt.__STRINGTOLD -@ extern __argc msvcrt.__argc -@ extern __argv msvcrt.__argv -@ cdecl __dllonexit(ptr ptr ptr) msvcrt.__dllonexit -@ cdecl __doserrno() msvcrt.__doserrno -@ cdecl __fpecode() msvcrt.__fpecode -@ cdecl __getmainargs(ptr ptr ptr long ptr) msvcrt.__getmainargs -@ extern __initenv msvcrt.__initenv -@ cdecl __isascii(long) msvcrt.__isascii -@ cdecl __iscsym(long) msvcrt.__iscsym -@ cdecl __iscsymf(long) msvcrt.__iscsymf -@ cdecl __lconv_init() msvcrt.__lconv_init -@ extern __mb_cur_max msvcrt.__mb_cur_max -@ cdecl -arch=i386 __p___argc() msvcrt.__p___argc -@ cdecl -arch=i386 __p___argv() msvcrt.__p___argv -@ cdecl -arch=i386 __p___initenv() msvcrt.__p___initenv -@ cdecl -arch=i386 __p___mb_cur_max() msvcrt.__p___mb_cur_max -@ cdecl -arch=i386 __p___wargv() msvcrt.__p___wargv -@ cdecl -arch=i386 __p___winitenv() msvcrt.__p___winitenv -@ cdecl -arch=i386 __p__acmdln() msvcrt.__p__acmdln -@ cdecl -arch=i386 __p__amblksiz() msvcrt.__p__amblksiz -@ cdecl -arch=i386 __p__commode() msvcrt.__p__commode -@ cdecl -arch=i386 __p__daylight() msvcrt.__p__daylight -@ cdecl -arch=i386 __p__dstbias() msvcrt.__p__dstbias -@ cdecl -arch=i386 __p__environ() msvcrt.__p__environ -@ cdecl -arch=i386 __p__fmode() msvcrt.__p__fmode -@ cdecl -arch=i386 __p__iob() msvcrt.__p__iob -@ cdecl -arch=i386 __p__mbctype() msvcrt.__p__mbctype -@ cdecl -arch=i386 __p__osver() msvcrt.__p__osver -@ cdecl -arch=i386 __p__pctype() msvcrt.__p__pctype -@ cdecl -arch=i386 __p__pgmptr() msvcrt.__p__pgmptr -@ cdecl -arch=i386 __p__pwctype() msvcrt.__p__pwctype -@ cdecl -arch=i386 __p__timezone() msvcrt.__p__timezone -@ cdecl -arch=i386 __p__tzname() msvcrt.__p__tzname -@ cdecl -arch=i386 __p__wcmdln() msvcrt.__p__wcmdln -@ cdecl -arch=i386 __p__wenviron() msvcrt.__p__wenviron -@ cdecl -arch=i386 __p__winmajor() msvcrt.__p__winmajor -@ cdecl -arch=i386 __p__winminor() msvcrt.__p__winminor -@ cdecl -arch=i386 __p__winver() msvcrt.__p__winver -@ cdecl -arch=i386 __p__wpgmptr() msvcrt.__p__wpgmptr -@ cdecl __pxcptinfoptrs() msvcrt.__pxcptinfoptrs -@ cdecl __set_app_type(long) msvcrt.__set_app_type -@ cdecl __setusermatherr(ptr) msvcrt.__setusermatherr -@ cdecl __threadhandle() msvcrt.__threadhandle -@ cdecl __threadid() msvcrt.__threadid -@ cdecl __toascii(long) msvcrt.__toascii -@ cdecl __unDName(long str ptr ptr long) msvcrt.__unDName -@ extern __wargv msvcrt.__wargv -@ cdecl __wgetmainargs(ptr ptr ptr long ptr) msvcrt.__wgetmainargs -@ extern __winitenv msvcrt.__winitenv -@ cdecl _abnormal_termination() msvcrt._abnormal_termination -@ cdecl _access(str long) msvcrt._access -@ extern _acmdln msvcrt._acmdln -@ stdcall _adj_fdiv_m16i(long) msvcrt._adj_fdiv_m16i -@ stdcall _adj_fdiv_m32(long) msvcrt._adj_fdiv_m32 -@ stdcall _adj_fdiv_m32i(long) msvcrt._adj_fdiv_m32i -@ stdcall _adj_fdiv_m64(long long) msvcrt._adj_fdiv_m64 -@ cdecl _adj_fdiv_r() msvcrt._adj_fdiv_r -@ stdcall _adj_fdivr_m16i(long) msvcrt._adj_fdivr_m16i -@ stdcall _adj_fdivr_m32(long) msvcrt._adj_fdivr_m32 -@ stdcall _adj_fdivr_m32i(long) msvcrt._adj_fdivr_m32i -@ stdcall _adj_fdivr_m64(long long) msvcrt._adj_fdivr_m64 -@ cdecl _adj_fpatan() msvcrt._adj_fpatan -@ cdecl _adj_fprem() msvcrt._adj_fprem -@ cdecl _adj_fprem1() msvcrt._adj_fprem1 -@ cdecl _adj_fptan() msvcrt._adj_fptan -@ extern _adjust_fdiv msvcrt._adjust_fdiv -@ extern _aexit_rtn msvcrt._aexit_rtn -@ cdecl _amsg_exit(long) msvcrt._amsg_exit -@ cdecl _assert(str str long) msvcrt._assert -@ cdecl _atodbl(ptr str) msvcrt._atodbl -@ cdecl _atoldbl(ptr str) msvcrt._atoldbl -@ cdecl _beep(long long) msvcrt._beep -@ cdecl _beginthread(ptr long ptr) msvcrt._beginthread -@ cdecl _beginthreadex(ptr long ptr ptr long ptr) msvcrt._beginthreadex -@ cdecl _c_exit() msvcrt._c_exit -@ cdecl _cabs(long) msvcrt._cabs -@ cdecl _cexit() msvcrt._cexit -@ cdecl _cgets(str) msvcrt._cgets -@ cdecl _chdir(str) msvcrt._chdir -@ cdecl _chdrive(long) msvcrt._chdrive -@ cdecl _chgsign( double ) msvcrt._chgsign -@ cdecl _chmod(str long) msvcrt._chmod -@ cdecl _chsize(long long) msvcrt._chsize -@ cdecl _clearfp() msvcrt._clearfp -@ cdecl _close(long) msvcrt._close -@ cdecl _commit(long) msvcrt._commit -@ extern _commode msvcrt._commode -@ cdecl _control87(long long) msvcrt._control87 -@ cdecl _controlfp(long long) msvcrt._controlfp -@ cdecl _copysign( double double ) msvcrt._copysign -@ varargs _cprintf(str) msvcrt._cprintf -@ cdecl _cputs(str) msvcrt._cputs -@ cdecl _creat(str long) msvcrt._creat -@ varargs _cscanf(str) msvcrt._cscanf -@ extern _ctype msvcrt._ctype -@ cdecl _cwait(ptr long long) msvcrt._cwait -@ extern _daylight msvcrt._daylight -@ extern _dstbias msvcrt._dstbias -@ cdecl _dup(long) msvcrt._dup -@ cdecl _dup2(long long) msvcrt._dup2 -@ cdecl _ecvt( double long ptr ptr) msvcrt._ecvt -@ cdecl _endthread() msvcrt._endthread -@ cdecl _endthreadex(long) msvcrt._endthreadex -@ extern _environ msvcrt._environ -@ cdecl _eof(long) msvcrt._eof -@ cdecl _errno() msvcrt._errno -@ cdecl _except_handler2(ptr ptr ptr ptr) msvcrt._except_handler2 -@ cdecl _except_handler3(ptr ptr ptr ptr) msvcrt._except_handler3 -@ varargs _execl(str str) msvcrt._execl -@ varargs _execle(str str) msvcrt._execle -@ varargs _execlp(str str) msvcrt._execlp -@ varargs _execlpe(str str) msvcrt._execlpe -@ cdecl _execv(str ptr) msvcrt._execv -@ cdecl _execve(str ptr ptr) msvcrt._execve -@ cdecl _execvp(str ptr) msvcrt._execvp -@ cdecl _execvpe(str ptr ptr) msvcrt._execvpe -@ cdecl _exit(long) msvcrt._exit -@ cdecl _expand(ptr long) msvcrt._expand -@ cdecl _fcloseall() msvcrt._fcloseall -@ cdecl _fcvt( double long ptr ptr) msvcrt._fcvt -@ cdecl _fdopen(long str) msvcrt._fdopen -@ cdecl _fgetchar() msvcrt._fgetchar -@ cdecl _fgetwchar() msvcrt._fgetwchar -@ cdecl _filbuf(ptr) msvcrt._filbuf -@ extern _fileinfo msvcrt._fileinfo -@ cdecl _filelength(long) msvcrt._filelength -@ cdecl -ret64 _filelengthi64(long) msvcrt._filelengthi64 -@ cdecl _fileno(ptr) msvcrt._fileno -@ cdecl _findclose(long) msvcrt._findclose -@ cdecl _findfirst(str ptr) msvcrt._findfirst -@ cdecl _findfirsti64(str ptr) msvcrt._findfirsti64 -@ cdecl _findnext(long ptr) msvcrt._findnext -@ cdecl _findnexti64(long ptr) msvcrt._findnexti64 -@ cdecl _finite( double ) msvcrt._finite -@ cdecl _flsbuf(long ptr) msvcrt._flsbuf -@ cdecl _flushall() msvcrt._flushall -@ extern _fmode msvcrt._fmode -@ cdecl _fpclass(double) msvcrt._fpclass -@ cdecl _fpieee_flt(long ptr ptr) msvcrt._fpieee_flt -@ cdecl _fpreset() msvcrt._fpreset -@ cdecl _fputchar(long) msvcrt._fputchar -@ cdecl _fputwchar(long) msvcrt._fputwchar -@ cdecl _fsopen(str str long) msvcrt._fsopen -@ cdecl _fstat(long ptr) msvcrt._fstat -@ cdecl _fstati64(long ptr) msvcrt._fstati64 -@ cdecl _ftime(ptr) msvcrt._ftime -@ cdecl -ret64 _ftol() msvcrt._ftol -@ cdecl _fullpath(ptr str long) msvcrt._fullpath -@ cdecl _futime(long ptr) msvcrt._futime -@ cdecl _gcvt( double long str) msvcrt._gcvt -@ cdecl _get_osfhandle(long) msvcrt._get_osfhandle -@ cdecl _getch() msvcrt._getch -@ cdecl _getche() msvcrt._getche -@ cdecl _getcwd(str long) msvcrt._getcwd -@ cdecl _getdcwd(long str long) msvcrt._getdcwd -@ cdecl _getdiskfree(long ptr) msvcrt._getdiskfree -@ cdecl _getdllprocaddr(long str long) msvcrt._getdllprocaddr -@ cdecl _getdrive() msvcrt._getdrive -@ cdecl _getdrives() msvcrt._getdrives -@ cdecl _getmaxstdio() msvcrt._getmaxstdio -@ cdecl _getmbcp() msvcrt._getmbcp -@ cdecl _getpid() msvcrt._getpid -@ cdecl _getsystime(ptr) msvcrt._getsystime -@ cdecl _getw(ptr) msvcrt._getw -@ cdecl _getws(ptr) msvcrt._getws -@ cdecl _global_unwind2(ptr) msvcrt._global_unwind2 -@ cdecl _heapadd(ptr long) msvcrt._heapadd -@ cdecl _heapchk() msvcrt._heapchk -@ cdecl _heapmin() msvcrt._heapmin -@ cdecl _heapset(long) msvcrt._heapset -@ cdecl _heapused(ptr ptr) msvcrt._heapused -@ cdecl _heapwalk(ptr) msvcrt._heapwalk -@ cdecl _hypot(double double) msvcrt._hypot -@ cdecl _initterm(ptr ptr) msvcrt._initterm -@ cdecl -i386 _inp(long) msvcrt._inp -@ cdecl -i386 _inpd(long) msvcrt._inpd -@ cdecl -i386 _inpw(long) msvcrt._inpw -@ extern _iob msvcrt._iob -@ cdecl _isatty(long) msvcrt._isatty -@ cdecl _isctype(long long) msvcrt._isctype -@ cdecl _ismbbalnum(long) msvcrt._ismbbalnum -@ cdecl _ismbbalpha(long) msvcrt._ismbbalpha -@ cdecl _ismbbgraph(long) msvcrt._ismbbgraph -@ cdecl _ismbbkalnum(long) msvcrt._ismbbkalnum -@ cdecl _ismbbkana(long) msvcrt._ismbbkana -@ cdecl _ismbbkprint(long) msvcrt._ismbbkprint -@ cdecl _ismbbkpunct(long) msvcrt._ismbbkpunct -@ cdecl _ismbblead(long) msvcrt._ismbblead -@ cdecl _ismbbprint(long) msvcrt._ismbbprint -@ cdecl _ismbbpunct(long) msvcrt._ismbbpunct -@ cdecl _ismbbtrail(long) msvcrt._ismbbtrail -@ cdecl _ismbcalnum(long) msvcrt._ismbcalnum -@ cdecl _ismbcalpha(long) msvcrt._ismbcalpha -@ cdecl _ismbcdigit(long) msvcrt._ismbcdigit -@ cdecl _ismbcgraph(long) msvcrt._ismbcgraph -@ cdecl _ismbchira(long) msvcrt._ismbchira -@ cdecl _ismbckata(long) msvcrt._ismbckata -@ cdecl _ismbcl0(long) msvcrt._ismbcl0 -@ cdecl _ismbcl1(long) msvcrt._ismbcl1 -@ cdecl _ismbcl2(long) msvcrt._ismbcl2 -@ cdecl _ismbclegal(long) msvcrt._ismbclegal -@ cdecl _ismbclower(long) msvcrt._ismbclower -@ cdecl _ismbcprint(long) msvcrt._ismbcprint -@ cdecl _ismbcpunct(long) msvcrt._ismbcpunct -@ cdecl _ismbcspace(long) msvcrt._ismbcspace -@ cdecl _ismbcsymbol(long) msvcrt._ismbcsymbol -@ cdecl _ismbcupper(long) msvcrt._ismbcupper -@ cdecl _ismbslead(ptr ptr) msvcrt._ismbslead -@ cdecl _ismbstrail(ptr ptr) msvcrt._ismbstrail -@ cdecl _isnan( double ) msvcrt._isnan -@ cdecl _itoa(long ptr long) msvcrt._itoa -@ cdecl _itow(long ptr long) msvcrt._itow -@ cdecl _j0(double) msvcrt._j0 -@ cdecl _j1(double) msvcrt._j1 -@ cdecl _jn(long double) msvcrt._jn -@ cdecl _kbhit() msvcrt._kbhit -@ cdecl _lfind(ptr ptr ptr long ptr) msvcrt._lfind -@ cdecl _loaddll(str) msvcrt._loaddll -@ cdecl _local_unwind2(ptr long) msvcrt._local_unwind2 -@ cdecl _locking(long long long) msvcrt._locking -@ cdecl _logb(double) msvcrt._logb -@ cdecl _longjmpex(ptr long) msvcrt._longjmpex -@ cdecl _lrotl(long long) msvcrt._lrotl -@ cdecl _lrotr(long long) msvcrt._lrotr -@ cdecl _lsearch(ptr ptr long long ptr) msvcrt._lsearch -@ cdecl _lseek(long long long) msvcrt._lseek -@ cdecl -ret64 _lseeki64(long long long long) msvcrt._lseeki64 -@ cdecl _ltoa(long ptr long) msvcrt._ltoa -@ cdecl _ltow(long ptr long) msvcrt._ltow -@ cdecl _makepath(str str str str str) msvcrt._makepath -@ cdecl _mbbtombc(long) msvcrt._mbbtombc -@ cdecl _mbbtype(long long) msvcrt._mbbtype -@ cdecl _mbccpy(str str) msvcrt._mbccpy -@ cdecl _mbcjistojms(long) msvcrt._mbcjistojms -@ cdecl _mbcjmstojis(long) msvcrt._mbcjmstojis -@ cdecl _mbclen(ptr) msvcrt._mbclen -@ cdecl _mbctohira(long) msvcrt._mbctohira -@ cdecl _mbctokata(long) msvcrt._mbctokata -@ cdecl _mbctolower(long) msvcrt._mbctolower -@ cdecl _mbctombb(long) msvcrt._mbctombb -@ cdecl _mbctoupper(long) msvcrt._mbctoupper -@ extern _mbctype msvcrt._mbctype -@ cdecl _mbsbtype(str long) msvcrt._mbsbtype -@ cdecl _mbscat(str str) msvcrt._mbscat -@ cdecl _mbschr(str long) msvcrt._mbschr -@ cdecl _mbscmp(str str) msvcrt._mbscmp -@ cdecl _mbscoll(str str) msvcrt._mbscoll -@ cdecl _mbscpy(ptr str) msvcrt._mbscpy -@ cdecl _mbscspn(str str) msvcrt._mbscspn -@ cdecl _mbsdec(ptr ptr) msvcrt._mbsdec -@ cdecl _mbsdup(str) msvcrt._mbsdup -@ cdecl _mbsicmp(str str) msvcrt._mbsicmp -@ cdecl _mbsicoll(str str) msvcrt._mbsicoll -@ cdecl _mbsinc(str) msvcrt._mbsinc -@ cdecl _mbslen(str) msvcrt._mbslen -@ cdecl _mbslwr(str) msvcrt._mbslwr -@ cdecl _mbsnbcat(str str long) msvcrt._mbsnbcat -@ cdecl _mbsnbcmp(str str long) msvcrt._mbsnbcmp -@ cdecl _mbsnbcnt(ptr long) msvcrt._mbsnbcnt -@ cdecl _mbsnbcoll(str str long) msvcrt._mbsnbcoll -@ cdecl _mbsnbcpy(ptr str long) msvcrt._mbsnbcpy -@ cdecl _mbsnbicmp(str str long) msvcrt._mbsnbicmp -@ cdecl _mbsnbicoll(str str long) msvcrt._mbsnbicoll -@ cdecl _mbsnbset(str long long) msvcrt._mbsnbset -@ cdecl _mbsncat(str str long) msvcrt._mbsncat -@ cdecl _mbsnccnt(str long) msvcrt._mbsnccnt -@ cdecl _mbsncmp(str str long) msvcrt._mbsncmp -@ cdecl _mbsncoll(str str long) msvcrt._mbsncoll -@ cdecl _mbsncpy(str str long) msvcrt._mbsncpy -@ cdecl _mbsnextc(str) msvcrt._mbsnextc -@ cdecl _mbsnicmp(str str long) msvcrt._mbsnicmp -@ cdecl _mbsnicoll(str str long) msvcrt._mbsnicoll -@ cdecl _mbsninc(str long) msvcrt._mbsninc -@ cdecl _mbsnset(str long long) msvcrt._mbsnset -@ cdecl _mbspbrk(str str) msvcrt._mbspbrk -@ cdecl _mbsrchr(str long) msvcrt._mbsrchr -@ cdecl _mbsrev(str) msvcrt._mbsrev -@ cdecl _mbsset(str long) msvcrt._mbsset -@ cdecl _mbsspn(str str) msvcrt._mbsspn -@ cdecl _mbsspnp(str str) msvcrt._mbsspnp -@ cdecl _mbsstr(str str) msvcrt._mbsstr -@ cdecl _mbstok(str str) msvcrt._mbstok -@ cdecl _mbstrlen(str) msvcrt._mbstrlen -@ cdecl _mbsupr(str) msvcrt._mbsupr -@ cdecl _memccpy(ptr ptr long long) msvcrt._memccpy -@ cdecl _memicmp(str str long) msvcrt._memicmp -@ cdecl _mkdir(str) msvcrt._mkdir -@ cdecl _mktemp(str) msvcrt._mktemp -@ cdecl _msize(ptr) msvcrt._msize +@ cdecl $I10_OUTPUT() MSVCRT_I10_OUTPUT +@ cdecl -arch=i386 _CIacos() +@ cdecl -arch=i386 _CIasin() +@ cdecl -arch=i386 _CIatan() +@ cdecl -arch=i386 _CIatan2() +@ cdecl -arch=i386 _CIcos() +@ cdecl -arch=i386 _CIcosh() +@ cdecl -arch=i386 _CIexp() +@ cdecl -arch=i386 _CIfmod() +@ cdecl -arch=i386 _CIlog() +@ cdecl -arch=i386 _CIlog10() +@ cdecl -arch=i386 _CIpow() +@ cdecl -arch=i386 _CIsin() +@ cdecl -arch=i386 _CIsinh() +@ cdecl -arch=i386 _CIsqrt() +@ cdecl -arch=i386 _CItan() +@ cdecl -arch=i386 _CItanh() +@ stdcall _CxxThrowException(long long) +@ cdecl -i386 _EH_prolog() +@ extern _HUGE +@ cdecl _XcptFilter(long ptr) +@ cdecl -i386 __CxxFrameHandler(ptr ptr ptr ptr) +@ stdcall __CxxLongjmpUnwind(ptr) +@ cdecl __RTCastToVoid(ptr) MSVCRT___RTCastToVoid +@ cdecl __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast +@ cdecl __RTtypeid(ptr) MSVCRT___RTtypeid +@ cdecl __STRINGTOLD(ptr ptr str long) +@ extern __argc +@ extern __argv +@ cdecl __dllonexit(ptr ptr ptr) +@ cdecl __doserrno() +@ cdecl __fpecode() +@ cdecl __getmainargs(ptr ptr ptr long ptr) +@ extern __initenv +@ cdecl __isascii(long) +@ cdecl __iscsym(long) +@ cdecl __iscsymf(long) +@ cdecl __lconv_init() +@ extern __mb_cur_max +@ cdecl -arch=i386 __p___argc() +@ cdecl -arch=i386 __p___argv() +@ cdecl -arch=i386 __p___initenv() +@ cdecl -arch=i386 __p___mb_cur_max() +@ cdecl -arch=i386 __p___wargv() +@ cdecl -arch=i386 __p___winitenv() +@ cdecl -arch=i386 __p__acmdln() +@ cdecl -arch=i386 __p__amblksiz() +@ cdecl -arch=i386 __p__commode() +@ cdecl -arch=i386 __p__daylight() +@ cdecl -arch=i386 __p__dstbias() +@ cdecl -arch=i386 __p__environ() +@ cdecl -arch=i386 __p__fmode() +@ cdecl -arch=i386 __p__iob() +@ cdecl -arch=i386 __p__mbctype() +@ cdecl -arch=i386 __p__osver() +@ cdecl -arch=i386 __p__pctype() +@ cdecl -arch=i386 __p__pgmptr() +@ cdecl -arch=i386 __p__pwctype() +@ cdecl -arch=i386 __p__timezone() +@ cdecl -arch=i386 __p__tzname() +@ cdecl -arch=i386 __p__wcmdln() +@ cdecl -arch=i386 __p__wenviron() +@ cdecl -arch=i386 __p__winmajor() +@ cdecl -arch=i386 __p__winminor() +@ cdecl -arch=i386 __p__winver() +@ cdecl -arch=i386 __p__wpgmptr() +@ cdecl __pxcptinfoptrs() +@ cdecl __set_app_type(long) +@ cdecl __setusermatherr(ptr) +@ cdecl __threadhandle() +@ cdecl __threadid() +@ cdecl __toascii(long) +@ cdecl __unDName(long str ptr ptr long) +@ extern __wargv +@ cdecl __wgetmainargs(ptr ptr ptr long ptr) +@ extern __winitenv +@ cdecl _abnormal_termination() +@ cdecl _access(str long) +@ extern _acmdln +@ stdcall _adj_fdiv_m16i(long) +@ stdcall _adj_fdiv_m32(long) +@ stdcall _adj_fdiv_m32i(long) +@ stdcall _adj_fdiv_m64(long long) +@ cdecl _adj_fdiv_r() +@ stdcall _adj_fdivr_m16i(long) +@ stdcall _adj_fdivr_m32(long) +@ stdcall _adj_fdivr_m32i(long) +@ stdcall _adj_fdivr_m64(long long) +@ cdecl _adj_fpatan() +@ cdecl _adj_fprem() +@ cdecl _adj_fprem1() +@ cdecl _adj_fptan() +@ extern _adjust_fdiv +@ extern _aexit_rtn +@ cdecl _amsg_exit(long) +@ cdecl _assert(str str long) +@ cdecl _atodbl(ptr str) +@ cdecl _atoldbl(ptr str) +@ cdecl _beep(long long) +@ cdecl _beginthread(ptr long ptr) +@ cdecl _beginthreadex(ptr long ptr ptr long ptr) +@ cdecl _c_exit() +@ cdecl _cabs(long) +@ cdecl _cexit() +@ cdecl _cgets(str) +@ cdecl _chdir(str) +@ cdecl _chdrive(long) +@ cdecl _chgsign( double ) +@ cdecl _chmod(str long) +@ cdecl _chsize(long long) +@ cdecl _clearfp() +@ cdecl _close(long) +@ cdecl _commit(long) +@ extern _commode +@ cdecl _control87(long long) +@ cdecl _controlfp(long long) +@ cdecl _copysign( double double ) +@ varargs _cprintf(str) +@ cdecl _cputs(str) +@ cdecl _creat(str long) +@ varargs _cscanf(str) +@ extern _ctype +@ cdecl _cwait(ptr long long) +@ extern _daylight +@ extern _dstbias +@ cdecl _dup(long) +@ cdecl _dup2(long long) +@ cdecl _ecvt( double long ptr ptr) +@ cdecl _endthread() +@ cdecl _endthreadex(long) +@ extern _environ +@ cdecl _eof(long) +@ cdecl _errno() +@ cdecl _except_handler2(ptr ptr ptr ptr) +@ cdecl _except_handler3(ptr ptr ptr ptr) +@ varargs _execl(str str) +@ varargs _execle(str str) +@ varargs _execlp(str str) +@ varargs _execlpe(str str) +@ cdecl _execv(str ptr) +@ cdecl _execve(str ptr ptr) +@ cdecl _execvp(str ptr) +@ cdecl _execvpe(str ptr ptr) +@ cdecl _exit(long) +@ cdecl _expand(ptr long) +@ cdecl _fcloseall() +@ cdecl _fcvt( double long ptr ptr) +@ cdecl _fdopen(long str) +@ cdecl _fgetchar() +@ cdecl _fgetwchar() +@ cdecl _filbuf(ptr) +@ extern _fileinfo +@ cdecl _filelength(long) +@ cdecl -ret64 _filelengthi64(long) +@ cdecl _fileno(ptr) +@ cdecl _findclose(long) +@ cdecl _findfirst(str ptr) +@ cdecl _findfirsti64(str ptr) +@ cdecl _findnext(long ptr) +@ cdecl _findnexti64(long ptr) +@ cdecl _finite( double ) +@ cdecl _flsbuf(long ptr) +@ cdecl _flushall() +@ extern _fmode +@ cdecl _fpclass(double) +@ cdecl _fpieee_flt(long ptr ptr) +@ cdecl _fpreset() +@ cdecl _fputchar(long) +@ cdecl _fputwchar(long) +@ cdecl _fsopen(str str long) +@ cdecl _fstat(long ptr) +@ cdecl _fstati64(long ptr) +@ cdecl _ftime(ptr) +@ cdecl -ret64 _ftol() +@ cdecl _fullpath(ptr str long) +@ cdecl _futime(long ptr) +@ cdecl _gcvt( double long str) +@ cdecl _get_osfhandle(long) +@ cdecl _getch() +@ cdecl _getche() +@ cdecl _getcwd(str long) +@ cdecl _getdcwd(long str long) +@ cdecl _getdiskfree(long ptr) +@ cdecl _getdllprocaddr(long str long) +@ cdecl _getdrive() +@ cdecl _getdrives() +@ cdecl _getmaxstdio() +@ cdecl _getmbcp() +@ cdecl _getpid() +@ cdecl _getsystime(ptr) +@ cdecl _getw(ptr) +@ cdecl _getws(ptr) +@ cdecl _global_unwind2(ptr) +@ cdecl _heapadd(ptr long) +@ cdecl _heapchk() +@ cdecl _heapmin() +@ cdecl _heapset(long) +@ cdecl _heapused(ptr ptr) +@ cdecl _heapwalk(ptr) +@ cdecl _hypot(double double) +@ cdecl _initterm(ptr ptr) +@ cdecl -i386 _inp(long) MSVCRT__inp +@ cdecl -i386 _inpd(long) MSVCRT__inpd +@ cdecl -i386 _inpw(long) MSVCRT__inpw +@ extern _iob +@ cdecl _isatty(long) +@ cdecl _isctype(long long) +@ cdecl _ismbbalnum(long) +@ cdecl _ismbbalpha(long) +@ cdecl _ismbbgraph(long) +@ cdecl _ismbbkalnum(long) +@ cdecl _ismbbkana(long) +@ cdecl _ismbbkprint(long) +@ cdecl _ismbbkpunct(long) +@ cdecl _ismbblead(long) +@ cdecl _ismbbprint(long) +@ cdecl _ismbbpunct(long) +@ cdecl _ismbbtrail(long) +@ cdecl _ismbcalnum(long) +@ cdecl _ismbcalpha(long) +@ cdecl _ismbcdigit(long) +@ cdecl _ismbcgraph(long) +@ cdecl _ismbchira(long) +@ cdecl _ismbckata(long) +@ cdecl _ismbcl0(long) +@ cdecl _ismbcl1(long) +@ cdecl _ismbcl2(long) +@ cdecl _ismbclegal(long) +@ cdecl _ismbclower(long) +@ cdecl _ismbcprint(long) +@ cdecl _ismbcpunct(long) +@ cdecl _ismbcspace(long) +@ cdecl _ismbcsymbol(long) +@ cdecl _ismbcupper(long) +@ cdecl _ismbslead(ptr ptr) +@ cdecl _ismbstrail(ptr ptr) +@ cdecl _isnan( double ) +@ cdecl _itoa(long ptr long) +@ cdecl _itow(long ptr long) +@ cdecl _j0(double) +@ cdecl _j1(double) +@ cdecl _jn(long double) +@ cdecl _kbhit() +@ cdecl _lfind(ptr ptr ptr long ptr) +@ cdecl _loaddll(str) +@ cdecl _local_unwind2(ptr long) +@ cdecl _locking(long long long) +@ cdecl _logb(double) +@ cdecl _longjmpex(ptr long) longjmp +@ cdecl _lrotl(long long) +@ cdecl _lrotr(long long) +@ cdecl _lsearch(ptr ptr long long ptr) +@ cdecl _lseek(long long long) +@ cdecl -ret64 _lseeki64(long long long long) +@ cdecl _ltoa(long ptr long) +@ cdecl _ltow(long ptr long) +@ cdecl _makepath(str str str str str) +@ cdecl _mbbtombc(long) +@ cdecl _mbbtype(long long) +@ cdecl _mbccpy(str str) +@ cdecl _mbcjistojms(long) +@ cdecl _mbcjmstojis(long) +@ cdecl _mbclen(ptr) +@ cdecl _mbctohira(long) +@ cdecl _mbctokata(long) +@ cdecl _mbctolower(long) +@ cdecl _mbctombb(long) +@ cdecl _mbctoupper(long) +@ extern _mbctype +@ cdecl _mbsbtype(str long) +@ cdecl _mbscat(str str) +@ cdecl _mbschr(str long) +@ cdecl _mbscmp(str str) +@ cdecl _mbscoll(str str) +@ cdecl _mbscpy(ptr str) +@ cdecl _mbscspn(str str) +@ cdecl _mbsdec(ptr ptr) +@ cdecl _mbsdup(str) +@ cdecl _mbsicmp(str str) +@ cdecl _mbsicoll(str str) +@ cdecl _mbsinc(str) +@ cdecl _mbslen(str) +@ cdecl _mbslwr(str) +@ cdecl _mbsnbcat(str str long) +@ cdecl _mbsnbcmp(str str long) +@ cdecl _mbsnbcnt(ptr long) +@ cdecl _mbsnbcoll(str str long) +@ cdecl _mbsnbcpy(ptr str long) +@ cdecl _mbsnbicmp(str str long) +@ cdecl _mbsnbicoll(str str long) +@ cdecl _mbsnbset(str long long) +@ cdecl _mbsncat(str str long) +@ cdecl _mbsnccnt(str long) +@ cdecl _mbsncmp(str str long) +@ cdecl _mbsncoll(str str long) +@ cdecl _mbsncpy(str str long) +@ cdecl _mbsnextc(str) +@ cdecl _mbsnicmp(str str long) +@ cdecl _mbsnicoll(str str long) +@ cdecl _mbsninc(str long) +@ cdecl _mbsnset(str long long) +@ cdecl _mbspbrk(str str) +@ cdecl _mbsrchr(str long) +@ cdecl _mbsrev(str) +@ cdecl _mbsset(str long) +@ cdecl _mbsspn(str str) +@ cdecl _mbsspnp(str str) +@ cdecl _mbsstr(str str) +@ cdecl _mbstok(str str) +@ cdecl _mbstrlen(str) +@ cdecl _mbsupr(str) +@ cdecl _memccpy(ptr ptr long long) +@ cdecl _memicmp(str str long) +@ cdecl _mkdir(str) +@ cdecl _mktemp(str) +@ cdecl _msize(ptr) @ stub _mtlock @ stub _mtunlock -@ cdecl _nextafter(double double) msvcrt._nextafter -@ cdecl _onexit(ptr) msvcrt._onexit -@ varargs _open(str long) msvcrt._open -@ cdecl _open_osfhandle(long long) msvcrt._open_osfhandle -@ extern _osver msvcrt._osver -@ cdecl -i386 _outp(long long) msvcrt._outp -@ cdecl -i386 _outpd(long long) msvcrt._outpd -@ cdecl -i386 _outpw(long long) msvcrt._outpw -@ cdecl _pclose(ptr) msvcrt._pclose -@ extern _pctype msvcrt._pctype -@ extern _pgmptr msvcrt._pgmptr -@ cdecl _pipe(ptr long long) msvcrt._pipe -@ cdecl _popen(str str) msvcrt._popen -@ cdecl _purecall() msvcrt._purecall -@ cdecl _putch(long) msvcrt._putch -@ cdecl _putenv(str) msvcrt._putenv -@ cdecl _putw(long ptr) msvcrt._putw -@ cdecl _putws(wstr) msvcrt._putws -@ extern _pwctype msvcrt._pwctype -@ cdecl _read(long ptr long) msvcrt._read -@ cdecl _rmdir(str) msvcrt._rmdir -@ cdecl _rmtmp() msvcrt._rmtmp -@ cdecl _rotl(long long) msvcrt._rotl -@ cdecl _rotr(long long) msvcrt._rotr -@ cdecl _safe_fdiv() msvcrt._safe_fdiv -@ cdecl _safe_fdivr() msvcrt._safe_fdivr -@ cdecl _safe_fprem() msvcrt._safe_fprem -@ cdecl _safe_fprem1() msvcrt._safe_fprem1 -@ cdecl _scalb( double long) msvcrt._scalb -@ cdecl _searchenv(str str ptr) msvcrt._searchenv -@ stdcall -i386 _seh_longjmp_unwind(ptr) msvcrt._seh_longjmp_unwind -@ cdecl _set_error_mode(long) msvcrt._set_error_mode -@ cdecl _seterrormode(long) msvcrt._seterrormode -@ cdecl -i386 _setjmp(ptr) msvcrt._setjmp -@ cdecl -i386 _setjmp3(ptr long) msvcrt._setjmp3 -@ cdecl _setmaxstdio(long) msvcrt._setmaxstdio -@ cdecl _setmbcp(long) msvcrt._setmbcp -@ cdecl _setmode(long long) msvcrt._setmode -@ cdecl _setsystime(ptr long) msvcrt._setsystime -@ cdecl _sleep(long) msvcrt._sleep -@ varargs _snprintf(str long str) msvcrt._snprintf -@ varargs _snwprintf(wstr long wstr) msvcrt._snwprintf -@ varargs _sopen(str long long) msvcrt._sopen -@ varargs _spawnl(long str str) msvcrt._spawnl -@ varargs _spawnle(long str str) msvcrt._spawnle -@ varargs _spawnlp(long str str) msvcrt._spawnlp -@ varargs _spawnlpe(long str str) msvcrt._spawnlpe -@ cdecl _spawnv(long str ptr) msvcrt._spawnv -@ cdecl _spawnve(long str ptr ptr) msvcrt._spawnve -@ cdecl _spawnvp(long str ptr) msvcrt._spawnvp -@ cdecl _spawnvpe(long str ptr ptr) msvcrt._spawnvpe -@ cdecl _splitpath(str ptr ptr ptr ptr) msvcrt._splitpath -@ cdecl _stat(str ptr) msvcrt._stat -@ cdecl _stati64(str ptr) msvcrt._stati64 -@ cdecl _statusfp() msvcrt._statusfp -@ cdecl _strcmpi(str str) msvcrt._strcmpi -@ cdecl _strdate(ptr) msvcrt._strdate -@ cdecl _strdup(str) msvcrt._strdup -@ cdecl _strerror(long) msvcrt._strerror -@ cdecl _stricmp(str str) msvcrt._stricmp -@ cdecl _stricoll(str str) msvcrt._stricoll -@ cdecl _strlwr(str) msvcrt._strlwr -@ cdecl _strncoll(str str long) msvcrt._strncoll -@ cdecl _strnicmp(str str long) msvcrt._strnicmp -@ cdecl _strnicoll(str str long) msvcrt._strnicoll -@ cdecl _strnset(str long long) msvcrt._strnset -@ cdecl _strrev(str) msvcrt._strrev -@ cdecl _strset(str long) msvcrt._strset -@ cdecl _strtime(ptr) msvcrt._strtime -@ cdecl _strupr(str) msvcrt._strupr -@ cdecl _swab(str str long) msvcrt._swab -@ extern _sys_errlist msvcrt._sys_errlist -@ extern _sys_nerr msvcrt._sys_nerr -@ cdecl _tell(long) msvcrt._tell -@ cdecl -ret64 _telli64(long) msvcrt._telli64 -@ cdecl _tempnam(str str) msvcrt._tempnam -@ extern _timezone msvcrt._timezone -@ cdecl _tolower(long) msvcrt._tolower -@ cdecl _toupper(long) msvcrt._toupper -@ extern _tzname msvcrt._tzname -@ cdecl _tzset() msvcrt._tzset -@ cdecl _ultoa(long ptr long) msvcrt._ultoa -@ cdecl _ultow(long ptr long) msvcrt._ultow -@ cdecl _umask(long) msvcrt._umask -@ cdecl _ungetch(long) msvcrt._ungetch -@ cdecl _unlink(str) msvcrt._unlink -@ cdecl _unloaddll(long) msvcrt._unloaddll -@ cdecl _utime(str ptr) msvcrt._utime -@ cdecl _vsnprintf(ptr long ptr ptr) msvcrt._vsnprintf -@ cdecl _vsnwprintf(ptr long wstr long) msvcrt._vsnwprintf -@ cdecl _waccess(wstr long) msvcrt._waccess -@ cdecl _wasctime(ptr) msvcrt._wasctime -@ cdecl _wchdir(wstr) msvcrt._wchdir -@ cdecl _wchmod(wstr long) msvcrt._wchmod -@ extern _wcmdln msvcrt._wcmdln -@ cdecl _wcreat(wstr long) msvcrt._wcreat -@ cdecl _wcsdup(wstr) msvcrt._wcsdup -@ cdecl _wcsicmp(wstr wstr) msvcrt._wcsicmp -@ cdecl _wcsicoll(wstr wstr) msvcrt._wcsicoll -@ cdecl _wcslwr(wstr) msvcrt._wcslwr -@ cdecl _wcsncoll(wstr wstr long) msvcrt._wcsncoll -@ cdecl _wcsnicmp(wstr wstr long) msvcrt._wcsnicmp -@ cdecl _wcsnicoll(wstr wstr long) msvcrt._wcsnicoll -@ cdecl _wcsnset(wstr long long) msvcrt._wcsnset -@ cdecl _wcsrev(wstr) msvcrt._wcsrev -@ cdecl _wcsset(wstr long) msvcrt._wcsset -@ cdecl _wcsupr(wstr) msvcrt._wcsupr -@ cdecl _wctime(ptr) msvcrt._wctime -@ extern _wenviron msvcrt._wenviron -@ varargs _wexecl(wstr wstr) msvcrt._wexecl -@ varargs _wexecle(wstr wstr) msvcrt._wexecle -@ varargs _wexeclp(wstr wstr) msvcrt._wexeclp -@ varargs _wexeclpe(wstr wstr) msvcrt._wexeclpe -@ varargs _wexecv(wstr ptr) msvcrt._wexecv -@ varargs _wexecve(wstr ptr ptr) msvcrt._wexecve -@ varargs _wexecvp(wstr ptr) msvcrt._wexecvp -@ varargs _wexecvpe(wstr ptr ptr) msvcrt._wexecvpe -@ cdecl _wfdopen(long wstr) msvcrt._wfdopen -@ cdecl _wfindfirst(wstr ptr) msvcrt._wfindfirst -@ cdecl _wfindfirsti64(wstr ptr) msvcrt._wfindfirsti64 -@ cdecl _wfindnext(long ptr) msvcrt._wfindnext -@ cdecl _wfindnexti64(long ptr) msvcrt._wfindnexti64 -@ cdecl _wfopen(wstr wstr) msvcrt._wfopen -@ cdecl _wfreopen(wstr wstr ptr) msvcrt._wfreopen -@ cdecl _wfsopen(wstr wstr long) msvcrt._wfsopen -@ cdecl _wfullpath(ptr wstr long) msvcrt._wfullpath -@ cdecl _wgetcwd(wstr long) msvcrt._wgetcwd -@ cdecl _wgetdcwd(long wstr long) msvcrt._wgetdcwd -@ cdecl _wgetenv(wstr) msvcrt._wgetenv -@ extern _winmajor msvcrt._winmajor -@ extern _winminor msvcrt._winminor -@ extern _winver msvcrt._winver -@ cdecl _wmakepath(wstr wstr wstr wstr wstr) msvcrt._wmakepath -@ cdecl _wmkdir(wstr) msvcrt._wmkdir -@ cdecl _wmktemp(wstr) msvcrt._wmktemp -@ varargs _wopen(wstr long) msvcrt._wopen -@ cdecl _wperror(wstr) msvcrt._wperror -@ extern _wpgmptr msvcrt._wpgmptr -@ cdecl _wpopen(wstr wstr) msvcrt._wpopen -@ cdecl _wputenv(wstr) msvcrt._wputenv -@ cdecl _wremove(wstr) msvcrt._wremove -@ cdecl _wrename(wstr wstr) msvcrt._wrename -@ cdecl _write(long ptr long) msvcrt._write -@ cdecl _wrmdir(wstr) msvcrt._wrmdir -@ cdecl _wsearchenv(wstr wstr ptr) msvcrt._wsearchenv -@ cdecl _wsetlocale(long wstr) msvcrt._wsetlocale -@ varargs _wsopen(wstr long long) msvcrt._wsopen -@ varargs _wspawnl(long wstr wstr) msvcrt._wspawnl -@ varargs _wspawnle(long wstr wstr) msvcrt._wspawnle -@ varargs _wspawnlp(long wstr wstr) msvcrt._wspawnlp -@ varargs _wspawnlpe(long wstr wstr) msvcrt._wspawnlpe -@ cdecl _wspawnv(long wstr ptr) msvcrt._wspawnv -@ cdecl _wspawnve(long wstr ptr ptr) msvcrt._wspawnve -@ cdecl _wspawnvp(long wstr ptr) msvcrt._wspawnvp -@ cdecl _wspawnvpe(long wstr ptr ptr) msvcrt._wspawnvpe -@ cdecl _wsplitpath(wstr wstr wstr wstr wstr) msvcrt._wsplitpath -@ cdecl _wstat(wstr ptr) msvcrt._wstat -@ cdecl _wstati64(wstr ptr) msvcrt._wstati64 -@ cdecl _wstrdate(ptr) msvcrt._wstrdate -@ cdecl _wstrtime(ptr) msvcrt._wstrtime -@ cdecl _wsystem(wstr) msvcrt._wsystem -@ cdecl _wtempnam(wstr wstr) msvcrt._wtempnam -@ cdecl _wtmpnam(ptr) msvcrt._wtmpnam -@ cdecl _wtoi(wstr) msvcrt._wtoi -@ cdecl _wtol(wstr) msvcrt._wtol -@ cdecl _wunlink(wstr) msvcrt._wunlink -@ cdecl _wutime(wstr ptr) msvcrt._wutime -@ cdecl _y0(double) msvcrt._y0 -@ cdecl _y1(double) msvcrt._y1 -@ cdecl _yn(long double ) msvcrt._yn -@ cdecl abort() msvcrt.abort -@ cdecl abs(long) msvcrt.abs -@ cdecl acos(double) msvcrt.acos -@ cdecl asctime(ptr) msvcrt.asctime -@ cdecl asin(double) msvcrt.asin -@ cdecl atan(double) msvcrt.atan -@ cdecl atan2(double double) msvcrt.atan2 -@ cdecl atexit(ptr) msvcrt.atexit -@ cdecl atof(str) msvcrt.atof -@ cdecl atoi(str) msvcrt.atoi -@ cdecl atol(str) msvcrt.atol -@ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch -@ cdecl calloc(long long) msvcrt.calloc -@ cdecl ceil(double) msvcrt.ceil -@ cdecl clearerr(ptr) msvcrt.clearerr -@ cdecl clock() msvcrt.clock -@ cdecl cos(double) msvcrt.cos -@ cdecl cosh(double) msvcrt.cosh -@ cdecl ctime(ptr) msvcrt.ctime -@ cdecl difftime(long long) msvcrt.difftime -@ cdecl div(long long) msvcrt.div -@ cdecl exit(long) msvcrt.exit -@ cdecl exp(double) msvcrt.exp -@ cdecl fabs(double) msvcrt.fabs -@ cdecl fclose(ptr) msvcrt.fclose -@ cdecl feof(ptr) msvcrt.feof -@ cdecl ferror(ptr) msvcrt.ferror -@ cdecl fflush(ptr) msvcrt.fflush -@ cdecl fgetc(ptr) msvcrt.fgetc -@ cdecl fgetpos(ptr ptr) msvcrt.fgetpos -@ cdecl fgets(ptr long ptr) msvcrt.fgets -@ cdecl fgetwc(ptr) msvcrt.fgetwc -@ cdecl fgetws(ptr long ptr) msvcrt.fgetws -@ cdecl floor(double) msvcrt.floor -@ cdecl fmod(double double) msvcrt.fmod -@ cdecl fopen(str str) msvcrt.fopen -@ varargs fprintf(ptr str) msvcrt.fprintf -@ cdecl fputc(long ptr) msvcrt.fputc -@ cdecl fputs(str ptr) msvcrt.fputs -@ cdecl fputwc(long ptr) msvcrt.fputwc -@ cdecl fputws(wstr ptr) msvcrt.fputws -@ cdecl fread(ptr long long ptr) msvcrt.fread -@ cdecl free(ptr) msvcrt.free -@ cdecl freopen(str str ptr) msvcrt.freopen -@ cdecl frexp(double ptr) msvcrt.frexp -@ varargs fscanf(ptr str) msvcrt.fscanf -@ cdecl fseek(ptr long long) msvcrt.fseek -@ cdecl fsetpos(ptr ptr) msvcrt.fsetpos -@ cdecl ftell(ptr) msvcrt.ftell -@ varargs fwprintf(ptr wstr) msvcrt.fwprintf -@ cdecl fwrite(ptr long long ptr) msvcrt.fwrite -@ varargs fwscanf(ptr wstr) msvcrt.fwscanf -@ cdecl getc(ptr) msvcrt.getc -@ cdecl getchar() msvcrt.getchar -@ cdecl getenv(str) msvcrt.getenv -@ cdecl gets(str) msvcrt.gets -@ cdecl getwc(ptr) msvcrt.getwc -@ cdecl getwchar() msvcrt.getwchar -@ cdecl gmtime(ptr) msvcrt.gmtime -@ cdecl is_wctype(long long) msvcrt.is_wctype -@ cdecl isalnum(long) msvcrt.isalnum -@ cdecl isalpha(long) msvcrt.isalpha -@ cdecl iscntrl(long) msvcrt.iscntrl -@ cdecl isdigit(long) msvcrt.isdigit -@ cdecl isgraph(long) msvcrt.isgraph -@ cdecl isleadbyte(long) msvcrt.isleadbyte -@ cdecl islower(long) msvcrt.islower -@ cdecl isprint(long) msvcrt.isprint -@ cdecl ispunct(long) msvcrt.ispunct -@ cdecl isspace(long) msvcrt.isspace -@ cdecl isupper(long) msvcrt.isupper -@ cdecl iswalnum(long) msvcrt.iswalnum -@ cdecl iswalpha(long) msvcrt.iswalpha -@ cdecl iswascii(long) msvcrt.iswascii -@ cdecl iswcntrl(long) msvcrt.iswcntrl -@ cdecl iswctype(long long) msvcrt.iswctype -@ cdecl iswdigit(long) msvcrt.iswdigit -@ cdecl iswgraph(long) msvcrt.iswgraph -@ cdecl iswlower(long) msvcrt.iswlower -@ cdecl iswprint(long) msvcrt.iswprint -@ cdecl iswpunct(long) msvcrt.iswpunct -@ cdecl iswspace(long) msvcrt.iswspace -@ cdecl iswupper(long) msvcrt.iswupper -@ cdecl iswxdigit(long) msvcrt.iswxdigit -@ cdecl isxdigit(long) msvcrt.isxdigit -@ cdecl labs(long) msvcrt.labs -@ cdecl ldexp( double long) msvcrt.ldexp -@ cdecl ldiv(long long) msvcrt.ldiv -@ cdecl localeconv() msvcrt.localeconv -@ cdecl localtime(ptr) msvcrt.localtime -@ cdecl log(double) msvcrt.log -@ cdecl log10(double) msvcrt.log10 -@ cdecl -i386 longjmp(ptr long) msvcrt.longjmp -@ cdecl malloc(long) msvcrt.malloc -@ cdecl mblen(ptr long) msvcrt.mblen -@ cdecl mbstowcs(ptr str long) msvcrt.mbstowcs -@ cdecl mbtowc(wstr str long) msvcrt.mbtowc -@ cdecl memchr(ptr long long) msvcrt.memchr -@ cdecl memcmp(ptr ptr long) msvcrt.memcmp -@ cdecl memcpy(ptr ptr long) msvcrt.memcpy -@ cdecl memmove(ptr ptr long) msvcrt.memmove -@ cdecl memset(ptr long long) msvcrt.memset -@ cdecl mktime(ptr) msvcrt.mktime -@ cdecl modf(double ptr) msvcrt.modf -@ cdecl perror(str) msvcrt.perror -@ cdecl pow(double double) msvcrt.pow -@ varargs printf(str) msvcrt.printf -@ cdecl putc(long ptr) msvcrt.putc -@ cdecl putchar(long) msvcrt.putchar -@ cdecl puts(str) msvcrt.puts -@ cdecl putwc(long ptr) msvcrt.putwc -@ cdecl putwchar(long) msvcrt.putwchar -@ cdecl qsort(ptr long long ptr) msvcrt.qsort -@ cdecl raise(long) msvcrt.raise -@ cdecl rand() msvcrt.rand -@ cdecl realloc(ptr long) msvcrt.realloc -@ cdecl remove(str) msvcrt.remove -@ cdecl rename(str str) msvcrt.rename -@ cdecl rewind(ptr) msvcrt.rewind -@ varargs scanf(str) msvcrt.scanf -@ cdecl setbuf(ptr ptr) msvcrt.setbuf -@ cdecl setlocale(long str) msvcrt.setlocale -@ cdecl setvbuf(ptr str long long) msvcrt.setvbuf -@ cdecl signal(long long) msvcrt.signal -@ cdecl sin(double) msvcrt.sin -@ cdecl sinh(double) msvcrt.sinh -@ varargs sprintf(ptr str) msvcrt.sprintf -@ cdecl sqrt(double) msvcrt.sqrt -@ cdecl srand(long) msvcrt.srand -@ varargs sscanf(str str) msvcrt.sscanf -@ cdecl strcat(str str) msvcrt.strcat -@ cdecl strchr(str long) msvcrt.strchr -@ cdecl strcmp(str str) msvcrt.strcmp -@ cdecl strcoll(str str) msvcrt.strcoll -@ cdecl strcpy(ptr str) msvcrt.strcpy -@ cdecl strcspn(str str) msvcrt.strcspn -@ cdecl strerror(long) msvcrt.strerror -@ cdecl strftime(str long str ptr) msvcrt.strftime -@ cdecl strlen(str) msvcrt.strlen -@ cdecl strncat(str str long) msvcrt.strncat -@ cdecl strncmp(str str long) msvcrt.strncmp -@ cdecl strncpy(ptr str long) msvcrt.strncpy -@ cdecl strpbrk(str str) msvcrt.strpbrk -@ cdecl strrchr(str long) msvcrt.strrchr -@ cdecl strspn(str str) msvcrt.strspn -@ cdecl strstr(str str) msvcrt.strstr -@ cdecl strtod(str ptr) msvcrt.strtod -@ cdecl strtok(str str) msvcrt.strtok -@ cdecl strtol(str ptr long) msvcrt.strtol -@ cdecl strtoul(str ptr long) msvcrt.strtoul -@ cdecl strxfrm(ptr str long) msvcrt.strxfrm -@ varargs swprintf(wstr wstr) msvcrt.swprintf -@ varargs swscanf(wstr wstr) msvcrt.swscanf -@ cdecl system(str) msvcrt.system -@ cdecl tan(double) msvcrt.tan -@ cdecl tanh(double) msvcrt.tanh -@ cdecl time(ptr) msvcrt.time -@ cdecl tmpfile() msvcrt.tmpfile -@ cdecl tmpnam(ptr) msvcrt.tmpnam -@ cdecl tolower(long) msvcrt.tolower -@ cdecl toupper(long) msvcrt.toupper -@ cdecl towlower(long) msvcrt.towlower -@ cdecl towupper(long) msvcrt.towupper -@ cdecl ungetc(long ptr) msvcrt.ungetc -@ cdecl ungetwc(long ptr) msvcrt.ungetwc -@ cdecl vfprintf(ptr str long) msvcrt.vfprintf -@ cdecl vfwprintf(ptr wstr long) msvcrt.vfwprintf -@ cdecl vprintf(str long) msvcrt.vprintf -@ cdecl vsprintf(ptr str ptr) msvcrt.vsprintf -@ cdecl vswprintf(ptr wstr long) msvcrt.vswprintf -@ cdecl vwprintf(wstr long) msvcrt.vwprintf -@ cdecl wcscat(wstr wstr) msvcrt.wcscat -@ cdecl wcschr(wstr long) msvcrt.wcschr -@ cdecl wcscmp(wstr wstr) msvcrt.wcscmp -@ cdecl wcscoll(wstr wstr) msvcrt.wcscoll -@ cdecl wcscpy(ptr wstr) msvcrt.wcscpy -@ cdecl wcscspn(wstr wstr) msvcrt.wcscspn -@ cdecl wcsftime(ptr long wstr ptr) msvcrt.wcsftime -@ cdecl wcslen(wstr) msvcrt.wcslen -@ cdecl wcsncat(wstr wstr long) msvcrt.wcsncat -@ cdecl wcsncmp(wstr wstr long) msvcrt.wcsncmp -@ cdecl wcsncpy(ptr wstr long) msvcrt.wcsncpy -@ cdecl wcspbrk(wstr wstr) msvcrt.wcspbrk -@ cdecl wcsrchr(wstr long) msvcrt.wcsrchr -@ cdecl wcsspn(wstr wstr) msvcrt.wcsspn -@ cdecl wcsstr(wstr wstr) msvcrt.wcsstr -@ cdecl wcstod(wstr ptr) msvcrt.wcstod -@ cdecl wcstok(wstr wstr) msvcrt.wcstok -@ cdecl wcstol(wstr ptr long) msvcrt.wcstol -@ cdecl wcstombs(ptr ptr long) msvcrt.wcstombs -@ cdecl wcstoul(wstr ptr long) msvcrt.wcstoul -@ cdecl wcsxfrm(ptr wstr long) msvcrt.wcsxfrm -@ cdecl wctomb(ptr long) msvcrt.wctomb -@ varargs wprintf(wstr) msvcrt.wprintf -@ varargs wscanf(wstr) msvcrt.wscanf +@ cdecl _nextafter(double double) +@ cdecl _onexit(ptr) +@ varargs _open(str long) +@ cdecl _open_osfhandle(long long) +@ extern _osver +@ cdecl -i386 _outp(long long) MSVCRT__outp +@ cdecl -i386 _outpd(long long) MSVCRT__outpd +@ cdecl -i386 _outpw(long long) MSVCRT__outpw +@ cdecl _pclose(ptr) +@ extern _pctype +@ extern _pgmptr +@ cdecl _pipe(ptr long long) +@ cdecl _popen(str str) +@ cdecl _purecall() +@ cdecl _putch(long) +@ cdecl _putenv(str) +@ cdecl _putw(long ptr) +@ cdecl _putws(wstr) +@ extern _pwctype +@ cdecl _read(long ptr long) +@ cdecl _rmdir(str) +@ cdecl _rmtmp() +@ cdecl _rotl(long long) +@ cdecl _rotr(long long) +@ cdecl _safe_fdiv() +@ cdecl _safe_fdivr() +@ cdecl _safe_fprem() +@ cdecl _safe_fprem1() +@ cdecl _scalb( double long) +@ cdecl _searchenv(str str ptr) +@ stdcall -i386 _seh_longjmp_unwind(ptr) +@ cdecl _set_error_mode(long) +@ cdecl _seterrormode(long) +@ cdecl -i386 _setjmp(ptr) +@ cdecl -i386 _setjmp3(ptr long) +@ cdecl _setmaxstdio(long) +@ cdecl _setmbcp(long) +@ cdecl _setmode(long long) +@ cdecl _setsystime(ptr long) +@ cdecl _sleep(long) +@ varargs _snprintf(str long str) +@ varargs _snwprintf(wstr long wstr) +@ varargs _sopen(str long long) +@ varargs _spawnl(long str str) +@ varargs _spawnle(long str str) +@ varargs _spawnlp(long str str) +@ varargs _spawnlpe(long str str) +@ cdecl _spawnv(long str ptr) +@ cdecl _spawnve(long str ptr ptr) +@ cdecl _spawnvp(long str ptr) +@ cdecl _spawnvpe(long str ptr ptr) +@ cdecl _splitpath(str ptr ptr ptr ptr) +@ cdecl _stat(str ptr) +@ cdecl _stati64(str ptr) +@ cdecl _statusfp() +@ cdecl _strcmpi(str str) +@ cdecl _strdate(ptr) +@ cdecl _strdup(str) +@ cdecl _strerror(long) +@ cdecl _stricmp(str str) +@ cdecl _stricoll(str str) +@ cdecl _strlwr(str) +@ cdecl _strncoll(str str long) +@ cdecl _strnicmp(str str long) +@ cdecl _strnicoll(str str long) +@ cdecl _strnset(str long long) +@ cdecl _strrev(str) +@ cdecl _strset(str long) +@ cdecl _strtime(ptr) +@ cdecl _strupr(str) +@ cdecl _swab(str str long) +@ extern _sys_errlist +@ extern _sys_nerr +@ cdecl _tell(long) +@ cdecl -ret64 _telli64(long) +@ cdecl _tempnam(str str) +@ extern _timezone +@ cdecl _tolower(long) +@ cdecl _toupper(long) +@ extern _tzname +@ cdecl _tzset() +@ cdecl _ultoa(long ptr long) +@ cdecl _ultow(long ptr long) +@ cdecl _umask(long) +@ cdecl _ungetch(long) +@ cdecl _unlink(str) +@ cdecl _unloaddll(long) +@ cdecl _utime(str ptr) +@ cdecl _vsnprintf(ptr long ptr ptr) +@ cdecl _vsnwprintf(ptr long wstr long) +@ cdecl _waccess(wstr long) +@ cdecl _wasctime(ptr) +@ cdecl _wchdir(wstr) +@ cdecl _wchmod(wstr long) +@ extern _wcmdln +@ cdecl _wcreat(wstr long) +@ cdecl _wcsdup(wstr) +@ cdecl _wcsicmp(wstr wstr) +@ cdecl _wcsicoll(wstr wstr) +@ cdecl _wcslwr(wstr) +@ cdecl _wcsncoll(wstr wstr long) +@ cdecl _wcsnicmp(wstr wstr long) +@ cdecl _wcsnicoll(wstr wstr long) +@ cdecl _wcsnset(wstr long long) +@ cdecl _wcsrev(wstr) +@ cdecl _wcsset(wstr long) +@ cdecl _wcsupr(wstr) +@ cdecl _wctime(ptr) +@ extern _wenviron +@ varargs _wexecl(wstr wstr) +@ varargs _wexecle(wstr wstr) +@ varargs _wexeclp(wstr wstr) +@ varargs _wexeclpe(wstr wstr) +@ varargs _wexecv(wstr ptr) +@ varargs _wexecve(wstr ptr ptr) +@ varargs _wexecvp(wstr ptr) +@ varargs _wexecvpe(wstr ptr ptr) +@ cdecl _wfdopen(long wstr) +@ cdecl _wfindfirst(wstr ptr) +@ cdecl _wfindfirsti64(wstr ptr) +@ cdecl _wfindnext(long ptr) +@ cdecl _wfindnexti64(long ptr) +@ cdecl _wfopen(wstr wstr) +@ cdecl _wfreopen(wstr wstr ptr) +@ cdecl _wfsopen(wstr wstr long) +@ cdecl _wfullpath(ptr wstr long) +@ cdecl _wgetcwd(wstr long) +@ cdecl _wgetdcwd(long wstr long) +@ cdecl _wgetenv(wstr) +@ extern _winmajor +@ extern _winminor +@ extern _winver +@ cdecl _wmakepath(wstr wstr wstr wstr wstr) +@ cdecl _wmkdir(wstr) +@ cdecl _wmktemp(wstr) +@ varargs _wopen(wstr long) +@ cdecl _wperror(wstr) +@ extern _wpgmptr +@ cdecl _wpopen(wstr wstr) +@ cdecl _wputenv(wstr) +@ cdecl _wremove(wstr) +@ cdecl _wrename(wstr wstr) +@ cdecl _write(long ptr long) +@ cdecl _wrmdir(wstr) +@ cdecl _wsearchenv(wstr wstr ptr) +@ cdecl _wsetlocale(long wstr) +@ varargs _wsopen(wstr long long) +@ varargs _wspawnl(long wstr wstr) +@ varargs _wspawnle(long wstr wstr) +@ varargs _wspawnlp(long wstr wstr) +@ varargs _wspawnlpe(long wstr wstr) +@ cdecl _wspawnv(long wstr ptr) +@ cdecl _wspawnve(long wstr ptr ptr) +@ cdecl _wspawnvp(long wstr ptr) +@ cdecl _wspawnvpe(long wstr ptr ptr) +@ cdecl _wsplitpath(wstr wstr wstr wstr wstr) +@ cdecl _wstat(wstr ptr) +@ cdecl _wstati64(wstr ptr) +@ cdecl _wstrdate(ptr) +@ cdecl _wstrtime(ptr) +@ cdecl _wsystem(wstr) +@ cdecl _wtempnam(wstr wstr) +@ cdecl _wtmpnam(ptr) +@ cdecl _wtoi(wstr) +@ cdecl _wtol(wstr) +@ cdecl _wunlink(wstr) +@ cdecl _wutime(wstr ptr) +@ cdecl _y0(double) +@ cdecl _y1(double) +@ cdecl _yn(long double ) +@ cdecl abort() +@ cdecl abs(long) +@ cdecl acos(double) +@ cdecl asctime(ptr) +@ cdecl asin(double) +@ cdecl atan(double) +@ cdecl atan2(double double) +@ extern atexit # <-- changing this will kill your cat, understand? +@ cdecl atof(str) +@ cdecl atoi(str) +@ cdecl atol(str) +@ cdecl bsearch(ptr ptr long long ptr) +@ cdecl calloc(long long) +@ cdecl ceil(double) +@ cdecl clearerr(ptr) +@ cdecl clock() +@ cdecl cos(double) +@ cdecl cosh(double) +@ cdecl ctime(ptr) +@ cdecl difftime(long long) +@ cdecl div(long long) +@ cdecl exit(long) +@ cdecl exp(double) +@ cdecl fabs(double) +@ cdecl fclose(ptr) +@ cdecl feof(ptr) +@ cdecl ferror(ptr) +@ cdecl fflush(ptr) +@ cdecl fgetc(ptr) +@ cdecl fgetpos(ptr ptr) +@ cdecl fgets(ptr long ptr) +@ cdecl fgetwc(ptr) +@ cdecl fgetws(ptr long ptr) +@ cdecl floor(double) +@ cdecl fmod(double double) +@ cdecl fopen(str str) +@ varargs fprintf(ptr str) +@ cdecl fputc(long ptr) +@ cdecl fputs(str ptr) +@ cdecl fputwc(long ptr) +@ cdecl fputws(wstr ptr) +@ cdecl fread(ptr long long ptr) +@ cdecl free(ptr) +@ cdecl freopen(str str ptr) +@ cdecl frexp(double ptr) +@ varargs fscanf(ptr str) +@ cdecl fseek(ptr long long) +@ cdecl fsetpos(ptr ptr) +@ cdecl ftell(ptr) +@ varargs fwprintf(ptr wstr) +@ cdecl fwrite(ptr long long ptr) +@ varargs fwscanf(ptr wstr) +@ cdecl getc(ptr) +@ cdecl getchar() +@ cdecl getenv(str) +@ cdecl gets(str) +@ cdecl getwc(ptr) +@ cdecl getwchar() +@ cdecl gmtime(ptr) +@ cdecl is_wctype(long long) +@ cdecl isalnum(long) +@ cdecl isalpha(long) +@ cdecl iscntrl(long) +@ cdecl isdigit(long) +@ cdecl isgraph(long) +@ cdecl isleadbyte(long) +@ cdecl islower(long) +@ cdecl isprint(long) +@ cdecl ispunct(long) +@ cdecl isspace(long) +@ cdecl isupper(long) +@ cdecl iswalnum(long) +@ cdecl iswalpha(long) +@ cdecl iswascii(long) +@ cdecl iswcntrl(long) +@ cdecl iswctype(long long) +@ cdecl iswdigit(long) +@ cdecl iswgraph(long) +@ cdecl iswlower(long) +@ cdecl iswprint(long) +@ cdecl iswpunct(long) +@ cdecl iswspace(long) +@ cdecl iswupper(long) +@ cdecl iswxdigit(long) +@ cdecl isxdigit(long) +@ cdecl labs(long) +@ cdecl ldexp( double long) +@ cdecl ldiv(long long) +@ cdecl localeconv() +@ cdecl localtime(ptr) +@ cdecl log(double) +@ cdecl log10(double) +@ cdecl -i386 longjmp(ptr long) +@ cdecl malloc(long) +@ cdecl mblen(ptr long) +@ cdecl mbstowcs(ptr str long) +@ cdecl mbtowc(wstr str long) +@ cdecl memchr(ptr long long) +@ cdecl memcmp(ptr ptr long) +@ cdecl memcpy(ptr ptr long) +@ cdecl memmove(ptr ptr long) +@ cdecl memset(ptr long long) +@ cdecl mktime(ptr) +@ cdecl modf(double ptr) +@ cdecl perror(str) +@ cdecl pow(double double) +@ varargs printf(str) +@ cdecl putc(long ptr) +@ cdecl putchar(long) +@ cdecl puts(str) +@ cdecl putwc(long ptr) fputwc +@ cdecl putwchar(long) _fputwchar +@ cdecl qsort(ptr long long ptr) +@ cdecl raise(long) +@ cdecl rand() +@ cdecl realloc(ptr long) +@ cdecl remove(str) +@ cdecl rename(str str) +@ cdecl rewind(ptr) +@ varargs scanf(str) +@ cdecl setbuf(ptr ptr) +@ cdecl setlocale(long str) +@ cdecl setvbuf(ptr str long long) +@ cdecl signal(long long) +@ cdecl sin(double) +@ cdecl sinh(double) +@ varargs sprintf(ptr str) +@ cdecl sqrt(double) +@ cdecl srand(long) +@ varargs sscanf(str str) +@ cdecl strcat(str str) +@ cdecl strchr(str long) +@ cdecl strcmp(str str) +@ cdecl strcoll(str str) +@ cdecl strcpy(ptr str) +@ cdecl strcspn(str str) +@ cdecl strerror(long) +@ cdecl strftime(str long str ptr) +@ cdecl strlen(str) +@ cdecl strncat(str str long) +@ cdecl strncmp(str str long) +@ cdecl strncpy(ptr str long) +@ cdecl strpbrk(str str) +@ cdecl strrchr(str long) +@ cdecl strspn(str str) +@ cdecl strstr(str str) +@ cdecl strtod(str ptr) +@ cdecl strtok(str str) +@ cdecl strtol(str ptr long) +@ cdecl strtoul(str ptr long) +@ cdecl strxfrm(ptr str long) +@ varargs swprintf(wstr wstr) +@ varargs swscanf(wstr wstr) +@ cdecl system(str) +@ cdecl tan(double) +@ cdecl tanh(double) +@ cdecl time(ptr) +@ cdecl tmpfile() +@ cdecl tmpnam(ptr) +@ cdecl tolower(long) +@ cdecl toupper(long) +@ cdecl towlower(long) +@ cdecl towupper(long) +@ cdecl ungetc(long ptr) +@ cdecl ungetwc(long ptr) +@ cdecl vfprintf(ptr str long) +@ cdecl vfwprintf(ptr wstr long) +@ cdecl vprintf(str long) +@ cdecl vsprintf(ptr str ptr) +@ cdecl vswprintf(ptr wstr long) +@ cdecl vwprintf(wstr long) +@ cdecl wcscat(wstr wstr) +@ cdecl wcschr(wstr long) +@ cdecl wcscmp(wstr wstr) +@ cdecl wcscoll(wstr wstr) +@ cdecl wcscpy(ptr wstr) +@ cdecl wcscspn(wstr wstr) +@ cdecl wcsftime(ptr long wstr ptr) +@ cdecl wcslen(wstr) +@ cdecl wcsncat(wstr wstr long) +@ cdecl wcsncmp(wstr wstr long) +@ cdecl wcsncpy(ptr wstr long) +@ cdecl wcspbrk(wstr wstr) +@ cdecl wcsrchr(wstr long) +@ cdecl wcsspn(wstr wstr) +@ cdecl wcsstr(wstr wstr) +@ cdecl wcstod(wstr ptr) +@ cdecl wcstok(wstr wstr) +@ cdecl wcstol(wstr ptr long) +@ cdecl wcstombs(ptr ptr long) +@ cdecl wcstoul(wstr ptr long) +@ cdecl wcsxfrm(ptr wstr long) +@ cdecl wctomb(ptr long) +@ varargs wprintf(wstr) +@ varargs wscanf(wstr) diff --git a/dll/win32/msvcrt40/stubs.c b/dll/win32/msvcrt40/stubs.c new file mode 100644 index 00000000000..d7cb577aee1 --- /dev/null +++ b/dll/win32/msvcrt40/stubs.c @@ -0,0 +1,67 @@ +#include + +#undef UNIMPLEMENTED +#define UNIMPLEMENTED __wine_spec_unimplemented_stub("msvcrt.dll", __FUNCTION__) + +int MSVCRT__inp( + unsigned short port) +{ + return _inp(port); +} + +unsigned short MSVCRT__inpw( + unsigned short port) +{ + return _inpw(port); +} + +unsigned long MSVCRT__inpd( + unsigned short port) +{ + return _inpd(port); +} + + +int MSVCRT__outp( + unsigned short port, + int databyte) +{ + return _outp(port, databyte); +} + +unsigned short MSVCRT__outpw( + unsigned short port, + unsigned short dataword) +{ + return _outpw(port, dataword); +} + +unsigned long MSVCRT__outpd( + unsigned short port, + unsigned long dataword) +{ + return _outpd(port, dataword); +} + +size_t _heapused( size_t *pUsed, size_t *pCommit ) +{ + UNIMPLEMENTED; + return( 0 ); +} + +int _fileinfo = 0; + +int _atodbl( + void * value, + char * str) +{ + UNIMPLEMENTED; + return 0; +} + +int _ismbbkprint( + unsigned int c) +{ + UNIMPLEMENTED; + return 0; +} diff --git a/dll/win32/netshell/lanstatusui.c b/dll/win32/netshell/lanstatusui.c index 1292ef1a843..2a5dd9bb089 100644 --- a/dll/win32/netshell/lanstatusui.c +++ b/dll/win32/netshell/lanstatusui.c @@ -252,6 +252,9 @@ UpdateLanStatus(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext) Shell_NotifyIconW(NIM_MODIFY, &nid); + if (nid.uFlags & NIF_ICON) + DestroyIcon(nid.hIcon); + pContext->dwInOctets = IfEntry.dwInOctets; pContext->dwOutOctets = IfEntry.dwOutOctets; @@ -1002,7 +1005,7 @@ InitializeNetTaskbarNotifications( ZeroMemory(&nid, sizeof(nid)); nid.cbSize = sizeof(nid); nid.uID = Index++; - nid.uFlags = NIF_ICON | NIF_MESSAGE; + nid.uFlags = NIF_MESSAGE; nid.u.uVersion = 3; nid.uCallbackMessage = WM_SHOWSTATUSDLG; nid.hWnd = hwndDlg; @@ -1022,6 +1025,8 @@ InitializeNetTaskbarNotifications( else if (pProps->Status == NCS_CONNECTED) nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE)); + if (nid.hIcon) + nid.uFlags |= NIF_ICON; wcscpy(nid.szTip, pProps->pszwName); nid.uFlags |= NIF_TIP; @@ -1043,6 +1048,9 @@ InitializeNetTaskbarNotifications( { CoTaskMemFree(pItem); } + + if (nid.uFlags & NIF_ICON) + DestroyIcon(nid.hIcon); } } }while(hr == S_OK); diff --git a/dll/win32/setupapi/CMakeLists.txt b/dll/win32/setupapi/CMakeLists.txt index 4cd101c30ec..f16f99287c1 100644 --- a/dll/win32/setupapi/CMakeLists.txt +++ b/dll/win32/setupapi/CMakeLists.txt @@ -57,5 +57,6 @@ add_importlibs(setupapi kernel32 ntdll) +add_pch(setupapi setupapi_private.h) add_cd_file(TARGET setupapi DESTINATION reactos/system32 FOR all) add_importlib_target(setupapi.spec) diff --git a/dll/win32/sfc_os/sfc_os.c b/dll/win32/sfc_os/sfc_os.c index 84fb96bace6..57a104d1139 100644 --- a/dll/win32/sfc_os/sfc_os.c +++ b/dll/win32/sfc_os/sfc_os.c @@ -142,3 +142,24 @@ BOOL WINAPI SfcGetNextProtectedFile(HANDLE RpcHandle, PPROTECTED_FILE_DATA ProtF return FALSE; } +/****************************************************************** + * SfcFileException [sfc_os.@] + * + * Disable the protection for the given file during one minute + * + * PARAMS + * dwUnknown0 [I] Set to 0 + * pwszFile [I] Name of the file to unprotect + * dwUnknown1 [I] Set to -1 + * + * RETURNS + * Failure: 1; + * Success: 0; + * + */ +DWORD WINAPI SfcFileException(DWORD dwUnknown0, PWCHAR pwszFile, DWORD dwUnknown1) +{ + UNIMPLEMENTED; + /* Always return success */ + return 0; +} \ No newline at end of file diff --git a/dll/win32/sfc_os/sfc_os.spec b/dll/win32/sfc_os/sfc_os.spec index 0fa440aff08..e8f44d9bf7a 100644 --- a/dll/win32/sfc_os/sfc_os.spec +++ b/dll/win32/sfc_os/sfc_os.spec @@ -2,7 +2,7 @@ @ stub sfc_os_2 @ stub sfc_os_3 @ stub sfc_os_4 -@ stub sfc_os_5 +@ stdcall SfcFileException(long ptr long) @ stub sfc_os_6 @ stub sfc_os_7 @ stdcall SfcGetNextProtectedFile(ptr ptr) diff --git a/dll/win32/syssetup/CMakeLists.txt b/dll/win32/syssetup/CMakeLists.txt index 433fb648119..9ebd0fe2bf7 100644 --- a/dll/win32/syssetup/CMakeLists.txt +++ b/dll/win32/syssetup/CMakeLists.txt @@ -15,9 +15,8 @@ list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/syssetup.def) add_library(syssetup SHARED ${SOURCE}) - +add_pch(syssetup precomp.h) set_module_type(syssetup win32dll) - target_link_libraries(syssetup uuid ${PSEH_LIB}) add_importlibs(syssetup diff --git a/dll/win32/syssetup/classinst.c b/dll/win32/syssetup/classinst.c index 7bf990c3347..e791e38030d 100644 --- a/dll/win32/syssetup/classinst.c +++ b/dll/win32/syssetup/classinst.c @@ -6,8 +6,7 @@ * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) */ -#include -#include +#include "precomp.h" #define NDEBUG #include diff --git a/dll/win32/syssetup/dllmain.c b/dll/win32/syssetup/dllmain.c index c4960461bdd..fe19b4c74ef 100644 --- a/dll/win32/syssetup/dllmain.c +++ b/dll/win32/syssetup/dllmain.c @@ -27,12 +27,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include - -#include "globals.h" - +#include "precomp.h" /* GLOBALS *******************************************************************/ diff --git a/dll/win32/syssetup/install.c b/dll/win32/syssetup/install.c index fb3a5808e9f..b098d6f859e 100644 --- a/dll/win32/syssetup/install.c +++ b/dll/win32/syssetup/install.c @@ -26,28 +26,7 @@ /* INCLUDES *****************************************************************/ -#define WIN32_NO_STATUS -#include -#define NTOS_MODE_USER -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "globals.h" -#include "resource.h" +#include "precomp.h" #define NDEBUG #include diff --git a/dll/win32/syssetup/logfile.c b/dll/win32/syssetup/logfile.c index 275cb440eef..ccbea67c9b3 100644 --- a/dll/win32/syssetup/logfile.c +++ b/dll/win32/syssetup/logfile.c @@ -25,12 +25,7 @@ */ /* INCLUDES *****************************************************************/ -#define WIN32_NO_STATUS -#include -#define NTOS_MODE_USER -#include - -#include +#include "precomp.h" /* GLOBALS ******************************************************************/ diff --git a/dll/win32/syssetup/precomp.h b/dll/win32/syssetup/precomp.h new file mode 100644 index 00000000000..7411b2fb32e --- /dev/null +++ b/dll/win32/syssetup/precomp.h @@ -0,0 +1,25 @@ +#define WIN32_NO_STATUS +#include +#include + +#define NTOS_MODE_USER +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "globals.h" +#include "resource.h" diff --git a/dll/win32/syssetup/wizard.c b/dll/win32/syssetup/wizard.c index 9547493ec51..bb57f7d11be 100644 --- a/dll/win32/syssetup/wizard.c +++ b/dll/win32/syssetup/wizard.c @@ -9,27 +9,11 @@ /* INCLUDES *****************************************************************/ -#include -#define WIN32_NO_STATUS -#include -#include -#include -#include -#include -#include -#include -#define NTOS_MODE_USER -#include -#include - -#include +#include "precomp.h" #define NDEBUG #include -#include "globals.h" -#include "resource.h" - #define VMWINST #define PM_REGISTRATION_NOTIFY (WM_APP + 1) diff --git a/dll/win32/uext2/CMakeLists.txt b/dll/win32/uext2/CMakeLists.txt index 19858c8f0b4..8a18c50a1ca 100644 --- a/dll/win32/uext2/CMakeLists.txt +++ b/dll/win32/uext2/CMakeLists.txt @@ -8,7 +8,7 @@ list(APPEND SOURCE add_library(uext2 SHARED ${SOURCE}) -set_module_type(uext2 win32dll) +set_module_type(uext2 nativedll) target_link_libraries(uext2 ext2lib) -add_importlibs(uext2 msvcrt kernel32 ntdll) +add_importlibs(uext2 ntdll) add_cd_file(TARGET uext2 DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/ufat/CMakeLists.txt b/dll/win32/ufat/CMakeLists.txt index 658ab44fb36..9548798a627 100644 --- a/dll/win32/ufat/CMakeLists.txt +++ b/dll/win32/ufat/CMakeLists.txt @@ -8,7 +8,7 @@ list(APPEND SOURCE add_library(ufat SHARED ${SOURCE}) -set_module_type(ufat win32dll) +set_module_type(ufat nativedll) target_link_libraries(ufat vfatlib) -add_importlibs(ufat msvcrt kernel32 ntdll) +add_importlibs(ufat ntdll) add_cd_file(TARGET ufat DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/ufatx/CMakeLists.txt b/dll/win32/ufatx/CMakeLists.txt index 98369440c6e..1c8704e7551 100644 --- a/dll/win32/ufatx/CMakeLists.txt +++ b/dll/win32/ufatx/CMakeLists.txt @@ -10,7 +10,7 @@ add_library(ufatx SHARED ${SOURCE}) set_entrypoint(ufatx 0) target_link_libraries(ufatx vfatxlib) -add_importlibs(ufatx msvcrt kernel32 ntdll) +add_importlibs(ufatx ntdll) add_importlib_target(ufatx.spec) add_dependencies(ufatx psdk) add_cd_file(TARGET ufatx DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/untfs/CMakeLists.txt b/dll/win32/untfs/CMakeLists.txt index 0416542d1e0..818df413b80 100644 --- a/dll/win32/untfs/CMakeLists.txt +++ b/dll/win32/untfs/CMakeLists.txt @@ -8,7 +8,7 @@ list(APPEND SOURCE add_library(untfs SHARED ${SOURCE}) -set_module_type(untfs win32dll) +set_module_type(untfs nativedll) target_link_libraries(untfs ntfslib) -add_importlibs(untfs msvcrt kernel32 ntdll) +add_importlibs(untfs ntdll) add_cd_file(TARGET untfs DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/urlmon/CMakeLists.txt b/dll/win32/urlmon/CMakeLists.txt index 99a95265ae4..cf667761faf 100644 --- a/dll/win32/urlmon/CMakeLists.txt +++ b/dll/win32/urlmon/CMakeLists.txt @@ -70,10 +70,7 @@ add_definitions( -DREGISTER_PROXY_DLL -D_URLMON_) +add_pch(urlmon urlmon_main.h) add_definitions(-DPROXY_CLSID_IS="{0x79EAC9F1,0xBAF9,0x11CE,{0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B}}") - -if(NOT MSVC) - # FIXME: msvc build - add_cd_file(TARGET urlmon DESTINATION reactos/system32 FOR all) -endif() +add_cd_file(TARGET urlmon DESTINATION reactos/system32 FOR all) add_importlib_target(urlmon.spec) diff --git a/dll/win32/urlmon/urlmon_urlmon.idl b/dll/win32/urlmon/urlmon_urlmon.idl index a8c9198c325..3ee8688c897 100644 --- a/dll/win32/urlmon/urlmon_urlmon.idl +++ b/dll/win32/urlmon/urlmon_urlmon.idl @@ -24,12 +24,14 @@ #define vi_progid(str) #endif +#ifndef __midl [ helpstring("URL Moniker"), threading(apartment), uuid(79eac9e0-baf9-11ce-8c82-00aa004ba90b) ] coclass StdURLMoniker { interface IMoniker; } +#endif [ helpstring("http: Asynchronous Pluggable Protocol Handler"), @@ -66,12 +68,14 @@ coclass HttpsProtocol { interface IInternetProtocolEx; interface IInternetPriori ] coclass MkProtocol { interface IInternetProtocolEx; interface IInternetPriority; } +#ifndef __midl [ helpstring("file:, local: Asynchronous Pluggable Protocol Handler"), threading(apartment), uuid(79eac9e7-baf9-11ce-8c82-00aa004ba90b) ] coclass FileProtocol { interface IInternetProtocolEx; interface IInternetPriority; } +#endif [ helpstring("CDL: Asynchronous Pluggable Protocol Handler"), diff --git a/drivers/bus/isapnp/CMakeLists.txt b/drivers/bus/isapnp/CMakeLists.txt index efb1f93256e..ea6eea4223b 100644 --- a/drivers/bus/isapnp/CMakeLists.txt +++ b/drivers/bus/isapnp/CMakeLists.txt @@ -8,5 +8,5 @@ add_library(isapnp SHARED set_module_type(isapnp kernelmodedriver) add_importlibs(isapnp ntoskrnl hal) - +add_pch(isapnp isapnp.h) add_cd_file(TARGET isapnp DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index 85fcb7887f4..75ee3ecdd9d 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -1,4 +1,3 @@ -#pragma once #include diff --git a/drivers/bus/pci/CMakeLists.txt b/drivers/bus/pci/CMakeLists.txt index d9c7bbb1e22..5917718dec2 100644 --- a/drivers/bus/pci/CMakeLists.txt +++ b/drivers/bus/pci/CMakeLists.txt @@ -7,5 +7,5 @@ add_library(pci SHARED set_module_type(pci kernelmodedriver) add_importlibs(pci ntoskrnl hal) - +add_pch(pci pci.h) add_cd_file(TARGET pci DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/bus/pci/pci.h b/drivers/bus/pci/pci.h index 2c4043396aa..f4001514391 100644 --- a/drivers/bus/pci/pci.h +++ b/drivers/bus/pci/pci.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/drivers/bus/pcmcia/CMakeLists.txt b/drivers/bus/pcmcia/CMakeLists.txt index 9c4b1a34aac..65ca6785e95 100644 --- a/drivers/bus/pcmcia/CMakeLists.txt +++ b/drivers/bus/pcmcia/CMakeLists.txt @@ -6,6 +6,6 @@ add_library(pcmcia SHARED pcmcia.rc) set_module_type(pcmcia kernelmodedriver) +add_pch(pcmcia pcmcia.h) add_importlibs(pcmcia ntoskrnl hal) - add_cd_file(TARGET pcmcia DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/filesystems/cdfs/fsctl.c b/drivers/filesystems/cdfs/fsctl.c index c15e84f6381..a8543dbfb73 100644 --- a/drivers/filesystems/cdfs/fsctl.c +++ b/drivers/filesystems/cdfs/fsctl.c @@ -63,10 +63,10 @@ CdfsGetPVDData(PUCHAR Buffer, for (i = 0; i < 2048; i += 4) { /* DON'T optimize this to ULONG!!! (breaks overflow) */ - Serial.Part[0] += Buffer[i+3]; - Serial.Part[1] += Buffer[i+2]; - Serial.Part[2] += Buffer[i+1]; Serial.Part[3] += Buffer[i+0]; + Serial.Part[2] += Buffer[i+1]; + Serial.Part[1] += Buffer[i+2]; + Serial.Part[0] += Buffer[i+3]; } CdInfo->SerialNumber = Serial.Value; diff --git a/drivers/filesystems/ext2/CMakeLists.txt b/drivers/filesystems/ext2/CMakeLists.txt index 4917fb14311..46375e4b9b7 100644 --- a/drivers/filesystems/ext2/CMakeLists.txt +++ b/drivers/filesystems/ext2/CMakeLists.txt @@ -24,7 +24,7 @@ list(APPEND SOURCE add_library(ext2fs SHARED ${SOURCE}) target_link_libraries(ext2fs ${PSEH_LIB}) - +add_pch(ext2fs inc/ext2fsd.h) set_module_type(ext2fs kernelmodedriver) add_importlibs(ext2fs ntoskrnl hal) diff --git a/drivers/filesystems/fastfat/create.c b/drivers/filesystems/fastfat/create.c index 864798a0a7a..3a2f5be23ba 100644 --- a/drivers/filesystems/fastfat/create.c +++ b/drivers/filesystems/fastfat/create.c @@ -545,7 +545,7 @@ VfatCreateFile ( PDEVICE_OBJECT DeviceObject, PIRP Irp ) RequestedDisposition == FILE_SUPERSEDE) { ULONG Attributes; - Attributes = Stack->Parameters.Create.FileAttributes; + Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL; vfatSplitPathName(&PathNameU, NULL, &FileNameU); Status = VfatAddEntry (DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions, diff --git a/drivers/filesystems/fs_rec/CMakeLists.txt b/drivers/filesystems/fs_rec/CMakeLists.txt index 14bfce865de..dba33ead1be 100644 --- a/drivers/filesystems/fs_rec/CMakeLists.txt +++ b/drivers/filesystems/fs_rec/CMakeLists.txt @@ -11,5 +11,5 @@ add_library(fs_rec SHARED set_module_type(fs_rec kernelmodedriver) add_importlibs(fs_rec ntoskrnl hal) - +add_pch(fs_rec fs_rec.h) add_cd_file(TARGET fs_rec DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/filesystems/mup/CMakeLists.txt b/drivers/filesystems/mup/CMakeLists.txt index 6ac375d8025..19712432332 100644 --- a/drivers/filesystems/mup/CMakeLists.txt +++ b/drivers/filesystems/mup/CMakeLists.txt @@ -6,5 +6,5 @@ add_library(mup SHARED set_module_type(mup kernelmodedriver) add_importlibs(mup ntoskrnl hal) - +add_pch(mup mup.h) add_cd_file(TARGET mup DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file diff --git a/drivers/filesystems/mup/create.c b/drivers/filesystems/mup/create.c index 1d96051dc7d..127a0756e5c 100644 --- a/drivers/filesystems/mup/create.c +++ b/drivers/filesystems/mup/create.c @@ -27,14 +27,11 @@ /* INCLUDES *****************************************************************/ -#include +#include "mup.h" //#define NDEBUG #include -#include "mup.h" - - /* FUNCTIONS ****************************************************************/ NTSTATUS NTAPI diff --git a/drivers/filesystems/mup/mup.c b/drivers/filesystems/mup/mup.c index cf75de6ffcd..845b6ba6699 100644 --- a/drivers/filesystems/mup/mup.c +++ b/drivers/filesystems/mup/mup.c @@ -27,14 +27,11 @@ /* INCLUDES *****************************************************************/ -#include +#include "mup.h" //#define NDEBUG #include -#include "mup.h" - - /* GLOBALS *****************************************************************/ diff --git a/drivers/filesystems/mup/mup.h b/drivers/filesystems/mup/mup.h index 7eca3a24f25..9bb1564aead 100644 --- a/drivers/filesystems/mup/mup.h +++ b/drivers/filesystems/mup/mup.h @@ -1,8 +1,7 @@ -#pragma once - -#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#include +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) typedef struct { @@ -10,8 +9,6 @@ typedef struct } DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; - - /* create.c */ DRIVER_DISPATCH MupCreate; NTSTATUS NTAPI @@ -19,7 +16,6 @@ MupCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); /* mup.c */ - NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); diff --git a/drivers/filesystems/npfs/create.c b/drivers/filesystems/npfs/create.c index 42bcacc07c8..a05c56902b9 100644 --- a/drivers/filesystems/npfs/create.c +++ b/drivers/filesystems/npfs/create.c @@ -984,7 +984,8 @@ NpfsClose(PDEVICE_OBJECT DeviceObject, /* Disconnect the pipes */ if (Ccb->OtherSide) { - ASSERT(Ccb->OtherSide->OtherSide == Ccb); + /* FIXME: Timo wants it rewritten */ + /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/ NpfsCcbSetOtherSide(Ccb->OtherSide, NULL); NpfsCcbSetOtherSide(Ccb, NULL); } diff --git a/drivers/input/i8042prt/CMakeLists.txt b/drivers/input/i8042prt/CMakeLists.txt index 1761b6111c5..ddeba6f0d09 100644 --- a/drivers/input/i8042prt/CMakeLists.txt +++ b/drivers/input/i8042prt/CMakeLists.txt @@ -16,5 +16,5 @@ add_library(i8042prt SHARED set_module_type(i8042prt kernelmodedriver) add_importlibs(i8042prt ntoskrnl hal) - +add_pch(i8042prt i8042prt.h) add_cd_file(TARGET i8042prt DESTINATION reactos/system32/drivers NO_CAB FOR all) \ No newline at end of file diff --git a/drivers/input/i8042prt/i8042prt.h b/drivers/input/i8042prt/i8042prt.h index 035feaf9ea9..a5aa4da41b4 100644 --- a/drivers/input/i8042prt/i8042prt.h +++ b/drivers/input/i8042prt/i8042prt.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/drivers/input/kbdclass/CMakeLists.txt b/drivers/input/kbdclass/CMakeLists.txt index e25e6307fa6..40ede5e00e4 100644 --- a/drivers/input/kbdclass/CMakeLists.txt +++ b/drivers/input/kbdclass/CMakeLists.txt @@ -6,9 +6,7 @@ add_library(kbdclass SHARED kbdclass.rc) set_module_type(kbdclass kernelmodedriver) - +add_pch(kbdclass kbdclass.h) target_link_libraries(kbdclass ${PSEH_LIB}) - add_importlibs(kbdclass ntoskrnl hal) - -add_cd_file(TARGET kbdclass DESTINATION reactos/system32/drivers NO_CAB FOR all) \ No newline at end of file +add_cd_file(TARGET kbdclass DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/input/mouclass/CMakeLists.txt b/drivers/input/mouclass/CMakeLists.txt index 13463ba849f..f5bf9656690 100644 --- a/drivers/input/mouclass/CMakeLists.txt +++ b/drivers/input/mouclass/CMakeLists.txt @@ -5,9 +5,7 @@ add_library(mouclass SHARED mouclass.rc) set_module_type(mouclass kernelmodedriver) - +add_pch(mouclass mouclass.h) target_link_libraries(mouclass ${PSEH_LIB}) - add_importlibs(mouclass ntoskrnl hal) - -add_cd_file(TARGET mouclass DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file +add_cd_file(TARGET mouclass DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/input/sermouse/CMakeLists.txt b/drivers/input/sermouse/CMakeLists.txt index 06a91c05f3d..42dfee9ff78 100644 --- a/drivers/input/sermouse/CMakeLists.txt +++ b/drivers/input/sermouse/CMakeLists.txt @@ -10,6 +10,6 @@ add_library(sermouse SHARED sermouse.rc) set_module_type(sermouse kernelmodedriver) +add_pch(sermouse sermouse.h) add_importlibs(sermouse ntoskrnl hal) - add_cd_file(TARGET sermouse DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/ksfilter/ks/CMakeLists.txt b/drivers/ksfilter/ks/CMakeLists.txt index 712848b6b2f..a6229f7cf9d 100644 --- a/drivers/ksfilter/ks/CMakeLists.txt +++ b/drivers/ksfilter/ks/CMakeLists.txt @@ -40,9 +40,8 @@ set_subsystem(ks native) set_image_base(ks 0x00010000) target_link_libraries(ks ${PSEH_LIB}) - +add_pch(ks priv.h) add_importlibs(ks ntoskrnl hal) add_dependencies(ks psdk bugcodes) - add_cd_file(TARGET ks DESTINATION reactos/system32/drivers FOR all) add_importlib_target(ks.spec) diff --git a/drivers/ksfilter/ks/driver.c b/drivers/ksfilter/ks/driver.c index c0195a4a97f..c6ef2c99389 100644 --- a/drivers/ksfilter/ks/driver.c +++ b/drivers/ksfilter/ks/driver.c @@ -8,9 +8,6 @@ #include "priv.h" -#include "ksfunc.h" - - /* @implemented */ diff --git a/drivers/ksfilter/ks/priv.h b/drivers/ksfilter/ks/priv.h index 8eb1959c288..395708f27e4 100644 --- a/drivers/ksfilter/ks/priv.h +++ b/drivers/ksfilter/ks/priv.h @@ -1,5 +1,3 @@ -#pragma once - #define _KSDDK_ #include diff --git a/drivers/network/afd/CMakeLists.txt b/drivers/network/afd/CMakeLists.txt index e0af27b0294..f28c2663924 100644 --- a/drivers/network/afd/CMakeLists.txt +++ b/drivers/network/afd/CMakeLists.txt @@ -23,7 +23,5 @@ target_link_libraries(afd ${PSEH_LIB}) set_module_type(afd kernelmodedriver) add_importlibs(afd ntoskrnl hal) - add_pch(afd include/afd.h) - add_cd_file(TARGET afd DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/network/afd/afd/bind.c b/drivers/network/afd/afd/bind.c index 91ee6e7cc04..20a0e1137a1 100644 --- a/drivers/network/afd/afd/bind.c +++ b/drivers/network/afd/afd/bind.c @@ -9,9 +9,6 @@ */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" NTSTATUS WarmSocketForBind( PAFD_FCB FCB ) { NTSTATUS Status; @@ -20,11 +17,11 @@ NTSTATUS WarmSocketForBind( PAFD_FCB FCB ) { FCB->LocalAddress->Address[0].AddressType)); if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) { - AFD_DbgPrint(MID_TRACE,("Null Device\n")); + AFD_DbgPrint(MIN_TRACE,("Null Device\n")); return STATUS_NO_SUCH_DEVICE; } if( !FCB->LocalAddress ) { - AFD_DbgPrint(MID_TRACE,("No local address\n")); + AFD_DbgPrint(MIN_TRACE,("No local address\n")); return STATUS_INVALID_PARAMETER; } diff --git a/drivers/network/afd/afd/connect.c b/drivers/network/afd/afd/connect.c index 38150d066e9..e11a5534621 100644 --- a/drivers/network/afd/afd/connect.c +++ b/drivers/network/afd/afd/connect.c @@ -8,9 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" NTSTATUS NTAPI AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, @@ -23,7 +20,10 @@ AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->ConnectOptionsSize == 0) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + } ASSERT(FCB->ConnectOptions); @@ -60,7 +60,8 @@ AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, } FCB->ConnectOptions = ExAllocatePool(PagedPool, ConnectOptionsSize); - if (!FCB->ConnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + if (!FCB->ConnectOptions) + return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); RtlCopyMemory(FCB->ConnectOptions, ConnectOptions, @@ -87,7 +88,10 @@ AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (BufferSize < sizeof(UINT)) + { + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + } if (FCB->ConnectOptions) { @@ -115,7 +119,10 @@ AfdGetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->ConnectDataSize == 0) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + } ASSERT(FCB->ConnectData); @@ -179,7 +186,10 @@ AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (BufferSize < sizeof(UINT)) + { + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + } if (FCB->ConnectData) { @@ -201,7 +211,7 @@ NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) { NTSTATUS Status; if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) { - AFD_DbgPrint(MID_TRACE,("Null Device\n")); + AFD_DbgPrint(MIN_TRACE,("Null Device\n")); return STATUS_NO_SUCH_DEVICE; } @@ -501,7 +511,7 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, break; default: - AFD_DbgPrint(MID_TRACE,("Inappropriate socket state %d for connect\n", + AFD_DbgPrint(MIN_TRACE,("Inappropriate socket state %d for connect\n", FCB->State)); break; } diff --git a/drivers/network/afd/afd/context.c b/drivers/network/afd/afd/context.c index e58398d1727..eb9cf7f4835 100644 --- a/drivers/network/afd/afd/context.c +++ b/drivers/network/afd/afd/context.c @@ -8,9 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" NTSTATUS NTAPI AfdGetContext( PDEVICE_OBJECT DeviceObject, PIRP Irp, @@ -46,7 +43,10 @@ AfdGetContextSize( PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) + { + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, sizeof(ULONG)); + } RtlCopyMemory(Irp->UserBuffer, &FCB->ContextSize, diff --git a/drivers/network/afd/afd/info.c b/drivers/network/afd/afd/info.c index 70e41a89115..16c46df4f02 100644 --- a/drivers/network/afd/afd/info.c +++ b/drivers/network/afd/afd/info.c @@ -8,10 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" -#include "pseh/pseh2.h" NTSTATUS NTAPI AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, @@ -88,13 +84,13 @@ AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, break; default: - AFD_DbgPrint(MID_TRACE,("Unknown info id %x\n", + AFD_DbgPrint(MIN_TRACE,("Unknown info id %x\n", InfoReq->InformationClass)); Status = STATUS_INVALID_PARAMETER; break; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - AFD_DbgPrint(MID_TRACE,("Exception executing GetInfo\n")); + AFD_DbgPrint(MIN_TRACE,("Exception executing GetInfo\n")); Status = STATUS_INVALID_PARAMETER; } _SEH2_END; @@ -183,6 +179,7 @@ AfdSetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, break; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + AFD_DbgPrint(MIN_TRACE,("Exception executing SetInfo\n")); Status = STATUS_INVALID_PARAMETER; } _SEH2_END; @@ -235,56 +232,27 @@ AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS NTAPI AfdGetPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; - PMDL Mdl = NULL; - PTDI_CONNECTION_INFORMATION ConnInfo = NULL; if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); - if (FCB->RemoteAddress == NULL || FCB->Connection.Object == NULL) { + if (FCB->RemoteAddress == NULL) { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } - if(NT_SUCCESS(Status = TdiBuildNullConnectionInfo - (&ConnInfo, - FCB->RemoteAddress->Address[0].AddressType))) + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= TaLengthOfTransportAddress(FCB->RemoteAddress)) + { + RtlCopyMemory(Irp->UserBuffer, FCB->RemoteAddress, TaLengthOfTransportAddress(FCB->RemoteAddress)); + Status = STATUS_SUCCESS; + } + else { - Mdl = IoAllocateMdl(ConnInfo, - sizeof(TDI_CONNECTION_INFORMATION) + - TaLengthOfTransportAddress(ConnInfo->RemoteAddress), - FALSE, - FALSE, - NULL); - - if (Mdl) - { - _SEH2_TRY { - MmProbeAndLockPages(Mdl, Irp->RequestorMode, IoModifyAccess); - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); - Status = _SEH2_GetExceptionCode(); - } _SEH2_END; - - if (NT_SUCCESS(Status)) - { - Status = TdiQueryInformation(FCB->Connection.Object, - TDI_QUERY_CONNECTION_INFO, - Mdl); - - if (NT_SUCCESS(Status)) - { - if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= TaLengthOfTransportAddress(ConnInfo->RemoteAddress)) - RtlCopyMemory(Irp->UserBuffer, ConnInfo->RemoteAddress, TaLengthOfTransportAddress(ConnInfo->RemoteAddress)); - else - Status = STATUS_BUFFER_TOO_SMALL; - } - } - } - - ExFreePool(ConnInfo); + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); + Status = STATUS_BUFFER_TOO_SMALL; } return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); diff --git a/drivers/network/afd/afd/listen.c b/drivers/network/afd/afd/listen.c index 27dd572f641..21e567a64e3 100644 --- a/drivers/network/afd/afd/listen.c +++ b/drivers/network/afd/afd/listen.c @@ -8,9 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" static NTSTATUS SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt, PIRP Irp, @@ -62,15 +59,6 @@ static NTSTATUS SatisfyPreAccept( PIRP Irp, PAFD_TDI_OBJECT_QELT Qelt ) { IPAddr = (PTA_IP_ADDRESS)&ListenReceive->Address; - if( !IPAddr ) { - if( Irp->MdlAddress ) UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) ); - Irp->IoStatus.Status = STATUS_NO_MEMORY; - Irp->IoStatus.Information = 0; - (void)IoSetCancelRoutine(Irp, NULL); - IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); - return STATUS_NO_MEMORY; - } - AFD_DbgPrint(MID_TRACE,("IPAddr->TAAddressCount %d\n", IPAddr->TAAddressCount)); AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressType %d\n", @@ -236,7 +224,7 @@ NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( FCB->State != SOCKET_STATE_BOUND ) { Status = STATUS_INVALID_PARAMETER; - AFD_DbgPrint(MID_TRACE,("Could not listen an unbound socket\n")); + AFD_DbgPrint(MIN_TRACE,("Could not listen an unbound socket\n")); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } @@ -316,7 +304,7 @@ NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp, SocketStateUnlock( FCB ); return Status; } else if (FCB->NonBlocking) { - AFD_DbgPrint(MID_TRACE,("No connection ready on a non-blocking socket\n")); + AFD_DbgPrint(MIN_TRACE,("No connection ready on a non-blocking socket\n")); return UnlockAndMaybeComplete(FCB, STATUS_CANT_WAIT, Irp, 0); } else { @@ -376,18 +364,23 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); ExFreePool( PendingConnObj ); + + FCB->EventSelectDisabled &= ~AFD_EVENT_ACCEPT; - if( !IsListEmpty( &FCB->PendingConnections ) ) { - FCB->PollState |= AFD_EVENT_ACCEPT; - FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; + if( !IsListEmpty( &FCB->PendingConnections ) ) + { + FCB->PollState |= AFD_EVENT_ACCEPT; + FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_ACCEPT; + } else + FCB->PollState &= ~AFD_EVENT_ACCEPT; SocketStateUnlock( FCB ); return Status; } } + + AFD_DbgPrint(MIN_TRACE,("No connection waiting\n")); return UnlockAndMaybeComplete( FCB, STATUS_UNSUCCESSFUL, Irp, 0 ); } diff --git a/drivers/network/afd/afd/lock.c b/drivers/network/afd/afd/lock.c index 93b41e07ab2..c64f8102e34 100644 --- a/drivers/network/afd/afd/lock.c +++ b/drivers/network/afd/afd/lock.c @@ -8,10 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" -#include "pseh/pseh2.h" PVOID GetLockedData(PIRP Irp, PIO_STACK_LOCATION IrpSp) { @@ -48,6 +44,7 @@ PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { } _SEH2_END; if( LockFailed ) { + AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n")); IoFreeMdl( Irp->MdlAddress ); Irp->MdlAddress = NULL; return NULL; @@ -74,6 +71,7 @@ PVOID LockRequest( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { } _SEH2_END; if( LockFailed ) { + AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n")); IoFreeMdl( Irp->MdlAddress ); Irp->MdlAddress = NULL; return NULL; @@ -158,7 +156,7 @@ PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count, if( MapBuf[i].Mdl ) { AFD_DbgPrint(MID_TRACE,("Probe and lock pages\n")); _SEH2_TRY { - MmProbeAndLockPages( MapBuf[i].Mdl, KernelMode, + MmProbeAndLockPages( MapBuf[i].Mdl, UserMode, Write ? IoModifyAccess : IoReadAccess ); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { LockFailed = TRUE; @@ -166,6 +164,7 @@ PAFD_WSABUF LockBuffers( PAFD_WSABUF Buf, UINT Count, AFD_DbgPrint(MID_TRACE,("MmProbeAndLock finished\n")); if( LockFailed ) { + AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n")); IoFreeMdl( MapBuf[i].Mdl ); MapBuf[i].Mdl = NULL; ExFreePool( NewBuf ); @@ -227,7 +226,10 @@ PAFD_HANDLE LockHandles( PAFD_HANDLE HandleArray, UINT HandleCount ) { } if( !NT_SUCCESS(Status) ) + { + AFD_DbgPrint(MIN_TRACE,("Failed to reference handles (0x%x)\n", Status)); FileObjects[i].Handle = 0; + } } if( !NT_SUCCESS(Status) ) { diff --git a/drivers/network/afd/afd/main.c b/drivers/network/afd/afd/main.c index ab1bae17f99..a1e664f6dab 100644 --- a/drivers/network/afd/afd/main.c +++ b/drivers/network/afd/afd/main.c @@ -13,15 +13,12 @@ /* INCLUDES */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" #if DBG /* See debug.h for debug/trace constants */ //DWORD DebugTraceLevel = DEBUG_ULTRA; -DWORD DebugTraceLevel = 0; +DWORD DebugTraceLevel = MIN_TRACE; #endif /* DBG */ @@ -52,7 +49,10 @@ AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->DisconnectOptionsSize == 0) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + } ASSERT(FCB->DisconnectOptions); @@ -116,7 +116,10 @@ AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (BufferSize < sizeof(UINT)) + { + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + } if (FCB->DisconnectOptions) { @@ -144,7 +147,10 @@ AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->DisconnectDataSize == 0) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + } ASSERT(FCB->DisconnectData); @@ -208,7 +214,10 @@ AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (BufferSize < sizeof(UINT)) + { + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + } if (FCB->DisconnectData) { @@ -241,7 +250,10 @@ AfdGetTdiHandles(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG) || IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*HandleData)) + { + AFD_DbgPrint(MIN_TRACE,("Buffer too small\n")); return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + } if ((*HandleFlags) & AFD_ADDRESS_HANDLE) HandleData->TdiAddressHandle = FCB->AddressFile.Handle; @@ -424,6 +436,7 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, InFlightRequest[1] = &FCB->ReceiveIrp; InFlightRequest[2] = &FCB->SendIrp; InFlightRequest[3] = &FCB->ConnectIrp; + InFlightRequest[4] = &FCB->DisconnectIrp; /* Cancel our pending requests */ for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) { @@ -588,12 +601,13 @@ DisconnectComplete(PDEVICE_OBJECT DeviceObject, IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT ); } - if (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE) - FCB->PollState |= AFD_EVENT_DISCONNECT; - else + if (!(FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE)) + { + /* Signal complete connection closure immediately */ FCB->PollState |= AFD_EVENT_ABORT; - FCB->PollStatus[FD_CLOSE_BIT] = Irp->IoStatus.Status; - PollReeval(FCB->DeviceExt, FCB->FileObject); + FCB->PollStatus[FD_CLOSE_BIT] = Irp->IoStatus.Status; + PollReeval(FCB->DeviceExt, FCB->FileObject); + } SocketStateUnlock(FCB); @@ -675,8 +689,11 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) { if( !FCB->ConnectCallInfo ) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); + } if (FCB->DisconnectPending) { @@ -703,6 +720,8 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->DisconnectFlags = Flags; FCB->DisconnectTimeout = DisReq->Timeout; FCB->DisconnectPending = TRUE; + FCB->SendClosed = TRUE; + FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_DISCONNECT); if (Status == STATUS_PENDING) @@ -730,11 +749,16 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (!(Flags & TDI_DISCONNECT_RELEASE)) { if (!FCB->RemoteAddress) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); + } ExFreePool(FCB->RemoteAddress); FCB->RemoteAddress = NULL; + + FCB->PollState &= ~AFD_EVENT_SEND; } } @@ -924,6 +948,54 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) return (Status); } +BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp) +{ + if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) + { + if (IrpSp->MajorFunction == IRP_MJ_READ || IrpSp->MajorFunction == IRP_MJ_WRITE) + { + /* read()/write() call - no extra buffers */ + return FALSE; + } + else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) + { + if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM) + { + /* recvfrom() call - extra buffers */ + return TRUE; + } + else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV) + { + /* recv() call - no extra buffers */ + return FALSE; + } + else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND || + IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND_DATAGRAM) + { + /* send()/sendto() call - no extra buffers */ + return FALSE; + } + else + { + /* Unknown IOCTL */ + ASSERT(FALSE); + return FALSE; + } + } + else + { + /* Unknown IRP_MJ code */ + ASSERT(FALSE); + return FALSE; + } + } + else + { + /* Connection-oriented never has extra buffers */ + return FALSE; + } +} + VOID CleanupPendingIrp(PAFD_FCB FCB, PIRP Irp, PIO_STACK_LOCATION IrpSp, PAFD_ACTIVE_POLL Poll) { @@ -935,14 +1007,13 @@ CleanupPendingIrp(PAFD_FCB FCB, PIRP Irp, PIO_STACK_LOCATION IrpSp, PAFD_ACTIVE_ IrpSp->MajorFunction == IRP_MJ_READ) { RecvReq = GetLockedData(Irp, IrpSp); - UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); + UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp)); } else if ((IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND || - IrpSp->MajorFunction == IRP_MJ_WRITE) && - !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) + IrpSp->MajorFunction == IRP_MJ_WRITE)) { SendReq = GetLockedData(Irp, IrpSp); - UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp)); } else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SELECT) { diff --git a/drivers/network/afd/afd/read.c b/drivers/network/afd/afd/read.c index cd4c6dae80f..e45aa00cf8c 100644 --- a/drivers/network/afd/afd/read.c +++ b/drivers/network/afd/afd/read.c @@ -22,75 +22,51 @@ * in flight. */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" -static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information ) +static VOID HandleReceiveComplete( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information ) { - if( ( Status == STATUS_SUCCESS && !Information ) || - ( !NT_SUCCESS( Status ) ) ) - { - /* The socket has been closed by the remote side */ - FCB->PollState |= AFD_EVENT_ABORT; + FCB->Recv.BytesUsed = 0; + + /* Receive successful with new data */ + if (Status == STATUS_SUCCESS && Information) + { + FCB->Recv.Content = Information; + } + /* Receive successful with no data (graceful closure) */ + else if (Status == STATUS_SUCCESS) + { + FCB->Recv.Content = 0; + FCB->TdiReceiveClosed = TRUE; + + /* Signal graceful receive shutdown */ + FCB->PollState |= AFD_EVENT_DISCONNECT; + FCB->PollStatus[FD_CLOSE_BIT] = Status; + + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + /* Receive failed with no data (unexpected closure) */ + else + { + FCB->Recv.Content = 0; + FCB->TdiReceiveClosed = TRUE; + + /* Signal complete connection failure immediately */ + FCB->PollState |= AFD_EVENT_CLOSE; FCB->PollStatus[FD_CLOSE_BIT] = Status; - + PollReeval( FCB->DeviceExt, FCB->FileObject ); - } + } } static BOOLEAN CantReadMore( PAFD_FCB FCB ) { UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed; - return !BytesAvailable && - (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_ABORT)); -} - -static BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp) -{ - if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) - { - if (IrpSp->MajorFunction == IRP_MJ_READ) - { - /* read() call - no extra buffers */ - return FALSE; - } - else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) - { - if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM) - { - /* recvfrom() call - extra buffers */ - return TRUE; - } - else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV) - { - /* recv() call - no extra buffers */ - return FALSE; - } - else - { - /* Unknown IOCTL */ - ASSERT(FALSE); - return FALSE; - } - } - else - { - /* Unknown IRP_MJ code */ - ASSERT(FALSE); - return FALSE; - } - } - else - { - /* Connection-oriented never has extra buffers */ - return FALSE; - } + return !BytesAvailable && FCB->TdiReceiveClosed; } static VOID RefillSocketBuffer( PAFD_FCB FCB ) { if( !FCB->ReceiveIrp.InFlightRequest && - !(FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_ABORT)) ) { + !FCB->TdiReceiveClosed ) { AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n")); TdiReceive( &FCB->ReceiveIrp.InFlightRequest, @@ -267,8 +243,11 @@ static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) { FCB->PollState |= AFD_EVENT_RECEIVE; FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else + } + else + { FCB->PollState &= ~AFD_EVENT_RECEIVE; + } AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus)); @@ -299,11 +278,7 @@ NTSTATUS NTAPI ReceiveComplete ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); FCB->ReceiveIrp.InFlightRequest = NULL; - FCB->Recv.Content = Irp->IoStatus.Information; - FCB->Recv.BytesUsed = 0; - if( FCB->State == SOCKET_STATE_CLOSED ) { - AFD_DbgPrint(MIN_TRACE,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n")); /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); @@ -325,7 +300,7 @@ NTSTATUS NTAPI ReceiveComplete return STATUS_INVALID_PARAMETER; } - HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information ); + HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information ); ReceiveActivity( FCB, NULL ); @@ -344,10 +319,11 @@ SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, GetLockedData(Irp, IrpSp); UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0; PAFD_MAPBUF Map; + BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp); Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount + - EXTRA_LOCK_BUFFERS); + (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0)); BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable ); @@ -357,12 +333,12 @@ SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, if( Map[0].Mdl ) { /* Copy the address */ - if( Map[1].Mdl && Map[2].Mdl ) { + if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) { AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n")); if( DatagramRecv->Address->TAAddressCount != 1 ) { AFD_DbgPrint - (MID_TRACE, + (MIN_TRACE, ("Wierd address count %d\n", DatagramRecv->Address->TAAddressCount)); } @@ -409,9 +385,19 @@ SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, *TotalBytesCopied = BytesToCopy; } - - Status = Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = BytesToCopy; + + if (*TotalBytesCopied == DatagramRecv->Len) + { + /* We copied the whole datagram */ + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + } + else + { + /* We only copied part of the datagram */ + Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + } + + Irp->IoStatus.Information = *TotalBytesCopied; if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) { @@ -443,7 +429,7 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) && FCB->State != SOCKET_STATE_CONNECTED && FCB->State != SOCKET_STATE_CONNECTING ) { - AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n", + AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n", FCB->State)); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); @@ -465,60 +451,46 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Irp, 0 ); } + FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { - if( !IsListEmpty( &FCB->DatagramList ) ) { - ListEntry = RemoveHeadList( &FCB->DatagramList ); - DatagramRecv = CONTAINING_RECORD - ( ListEntry, AFD_STORED_DATAGRAM, ListEntry ); - if( DatagramRecv->Len > RecvReq->BufferArray[0].len && - !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { - InsertHeadList( &FCB->DatagramList, - &DatagramRecv->ListEntry ); - Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = DatagramRecv->Len; - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); - } else { - Status = SatisfyPacketRecvRequest - ( FCB, Irp, DatagramRecv, - (PUINT)&Irp->IoStatus.Information ); - - if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) - { - InsertHeadList(&FCB->DatagramList, - &DatagramRecv->ListEntry); - } - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); + if (!IsListEmpty(&FCB->DatagramList)) + { + ListEntry = RemoveHeadList(&FCB->DatagramList); + DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); + Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, + (PUINT)&Irp->IoStatus.Information); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); + } + + if (!IsListEmpty(&FCB->DatagramList)) + { + FCB->PollState |= AFD_EVENT_RECEIVE; + FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); } - } else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { + else + FCB->PollState &= ~AFD_EVENT_RECEIVE; + + UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); + + return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); + } + else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) + { AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); Status = STATUS_CANT_WAIT; FCB->PollState &= ~AFD_EVENT_RECEIVE; UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - } else { + } + else + { FCB->PollState &= ~AFD_EVENT_RECEIVE; return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } @@ -651,33 +623,26 @@ PacketSocketRecvComplete( AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n", RecvReq, DatagramRecv)); - if( DatagramRecv->Len > RecvReq->BufferArray[0].len && - !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { - InsertHeadList( &FCB->DatagramList, - &DatagramRecv->ListEntry ); - Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - NextIrp->IoStatus.Information = DatagramRecv->Len; - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); - if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); - (void)IoSetCancelRoutine(NextIrp, NULL); - IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); - } else { - AFD_DbgPrint(MID_TRACE,("Satisfying\n")); - Status = SatisfyPacketRecvRequest - ( FCB, NextIrp, DatagramRecv, - (PUINT)&NextIrp->IoStatus.Information ); - if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) - { - InsertHeadList(&FCB->DatagramList, - &DatagramRecv->ListEntry); - } - AFD_DbgPrint(MID_TRACE,("Unlocking\n")); - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); - if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); - AFD_DbgPrint(MID_TRACE,("Completing\n")); - (void)IoSetCancelRoutine(NextIrp, NULL); - IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); - } + AFD_DbgPrint(MID_TRACE,("Satisfying\n")); + Status = SatisfyPacketRecvRequest + ( FCB, NextIrp, DatagramRecv, + (PUINT)&NextIrp->IoStatus.Information ); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); + } + + AFD_DbgPrint(MID_TRACE,("Unlocking\n")); + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); + if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); + + AFD_DbgPrint(MID_TRACE,("Completing\n")); + (void)IoSetCancelRoutine(NextIrp, NULL); + NextIrp->IoStatus.Status = Status; + + IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { @@ -723,8 +688,11 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND ) + { + AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); return UnlockAndMaybeComplete ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); + } if( !(RecvReq = LockRequest( Irp, IrpSp )) ) return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); @@ -742,59 +710,45 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } - if( !IsListEmpty( &FCB->DatagramList ) ) { - ListEntry = RemoveHeadList( &FCB->DatagramList ); - DatagramRecv = CONTAINING_RECORD - ( ListEntry, AFD_STORED_DATAGRAM, ListEntry ); - if( DatagramRecv->Len > RecvReq->BufferArray[0].len && - !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { - InsertHeadList( &FCB->DatagramList, - &DatagramRecv->ListEntry ); - Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = DatagramRecv->Len; - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); - } else { - Status = SatisfyPacketRecvRequest - ( FCB, Irp, DatagramRecv, - (PUINT)&Irp->IoStatus.Information ); - - if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) - { - InsertHeadList(&FCB->DatagramList, - &DatagramRecv->ListEntry); - } - - if( !IsListEmpty( &FCB->DatagramList ) ) { - FCB->PollState |= AFD_EVENT_RECEIVE; - FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else - FCB->PollState &= ~AFD_EVENT_RECEIVE; - - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); + FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE; - return UnlockAndMaybeComplete - ( FCB, Status, Irp, Irp->IoStatus.Information ); - } - } else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { - AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); - Status = STATUS_CANT_WAIT; - FCB->PollState &= ~AFD_EVENT_RECEIVE; - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); - return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - } else { - FCB->PollState &= ~AFD_EVENT_RECEIVE; - return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); + if (!IsListEmpty(&FCB->DatagramList)) + { + ListEntry = RemoveHeadList(&FCB->DatagramList); + DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry); + Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv, + (PUINT)&Irp->IoStatus.Information); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); + } + + if (!IsListEmpty(&FCB->DatagramList)) + { + FCB->PollState |= AFD_EVENT_RECEIVE; + FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + else + FCB->PollState &= ~AFD_EVENT_RECEIVE; + + UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE); + + return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information); + } + else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) + { + AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); + Status = STATUS_CANT_WAIT; + FCB->PollState &= ~AFD_EVENT_RECEIVE; + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); + } + else + { + FCB->PollState &= ~AFD_EVENT_RECEIVE; + return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } } diff --git a/drivers/network/afd/afd/select.c b/drivers/network/afd/afd/select.c index 591d66ed975..4d425a4c99e 100644 --- a/drivers/network/afd/afd/select.c +++ b/drivers/network/afd/afd/select.c @@ -8,9 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" static VOID PrintEvents( ULONG Events ) { #if DBG @@ -293,7 +290,10 @@ AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, NULL ); if( !NT_SUCCESS(Status) ) + { + AFD_DbgPrint(MIN_TRACE,("Failed reference event (0x%x)\n", Status)); FCB->EventSelect = NULL; + } else FCB->EventSelectTriggers = EventSelectInfo->Events; } else { @@ -302,8 +302,15 @@ AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = STATUS_SUCCESS; } - if( FCB->EventSelect && (FCB->PollState & FCB->EventSelectTriggers) ) { + if((FCB->EventSelect) && + (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) + { AFD_DbgPrint(MID_TRACE,("Setting event %x\n", FCB->EventSelect)); + + /* Disable the events that triggered the select until the reenabling function is called */ + FCB->EventSelectDisabled |= (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled)); + + /* Set the application's event */ KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); } @@ -405,8 +412,15 @@ VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) { KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); - if( FCB->EventSelect && (FCB->PollState & FCB->EventSelectTriggers) ) { + if((FCB->EventSelect) && + (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled))) + { AFD_DbgPrint(MID_TRACE,("Setting event %x\n", FCB->EventSelect)); + + /* Disable the events that triggered the select until the reenabling function is called */ + FCB->EventSelectDisabled |= (FCB->PollState & (FCB->EventSelectTriggers & ~FCB->EventSelectDisabled)); + + /* Set the application's event */ KeSetEvent( FCB->EventSelect, IO_NETWORK_INCREMENT, FALSE ); } diff --git a/drivers/network/afd/afd/tdi.c b/drivers/network/afd/afd/tdi.c index 9a18dd21bdc..cfd187a6f87 100644 --- a/drivers/network/afd/afd/tdi.c +++ b/drivers/network/afd/afd/tdi.c @@ -30,7 +30,7 @@ static VOID DisplayBuffer( return; } - AFD_DbgPrint(MIN_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size)); + AFD_DbgPrint(MID_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size)); p = (PCHAR)Buffer; for (i = 0; i < Size; i++) { @@ -236,6 +236,7 @@ NTSTATUS TdiQueryMaxDatagramLength( if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n")); IoFreeMdl(Mdl); ExFreePool(Buffer); return Status; @@ -1005,9 +1006,9 @@ NTSTATUS TdiReceive( } _SEH2_TRY { - AFD_DbgPrint(MIN_TRACE, ("probe and lock\n")); + AFD_DbgPrint(MID_TRACE, ("probe and lock\n")); MmProbeAndLockPages(Mdl, (*Irp)->RequestorMode, IoModifyAccess); - AFD_DbgPrint(MIN_TRACE, ("probe and lock done\n")); + AFD_DbgPrint(MID_TRACE, ("probe and lock done\n")); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); IoFreeMdl(Mdl); diff --git a/drivers/network/afd/afd/tdiconn.c b/drivers/network/afd/afd/tdiconn.c index 4aa764c230f..f413c910257 100644 --- a/drivers/network/afd/afd/tdiconn.c +++ b/drivers/network/afd/afd/tdiconn.c @@ -8,45 +8,65 @@ * 20040708 Created */ #include -#include -#include "debug.h" -#include "tdiconn.h" UINT TdiAddressSizeFromType( UINT AddressType ) { switch( AddressType ) { case TDI_ADDRESS_TYPE_IP: - return sizeof(TA_IP_ADDRESS); + return TDI_ADDRESS_LENGTH_IP; case TDI_ADDRESS_TYPE_APPLETALK: - return sizeof(TA_APPLETALK_ADDRESS); + return TDI_ADDRESS_LENGTH_APPLETALK; case TDI_ADDRESS_TYPE_NETBIOS: - return sizeof(TA_NETBIOS_ADDRESS); + return TDI_ADDRESS_LENGTH_NETBIOS; /* case TDI_ADDRESS_TYPE_NS: */ case TDI_ADDRESS_TYPE_IPX: - return sizeof(TA_IPX_ADDRESS); + return TDI_ADDRESS_LENGTH_IPX; case TDI_ADDRESS_TYPE_VNS: - return sizeof(TA_VNS_ADDRESS); + return TDI_ADDRESS_LENGTH_VNS; default: DbgPrint("TdiAddressSizeFromType - invalid type: %x\n", AddressType); return 0; } } -UINT TaLengthOfAddress( PTA_ADDRESS Addr ) { - UINT AddrLen = 2 * sizeof( USHORT ) + Addr->AddressLength; +UINT TaLengthOfAddress( PTA_ADDRESS Addr ) +{ + UINT AddrLen = Addr->AddressLength; + + if (!AddrLen) + return 0; + + AddrLen += 2 * sizeof( USHORT ); + AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); + return AddrLen; } -UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr ) { - UINT AddrLen = sizeof(ULONG) + TaLengthOfAddress(&Addr->Address[0]); +UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr ) +{ + UINT AddrLen = TaLengthOfAddress(&Addr->Address[0]); + + if (!AddrLen) + return 0; + + AddrLen += sizeof(ULONG); + AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); + return AddrLen; } UINT TaLengthOfTransportAddressByType(UINT AddressType) { - UINT AddrLen = sizeof(ULONG) + 2 * sizeof(USHORT) + TdiAddressSizeFromType(AddressType); + UINT AddrLen = TdiAddressSizeFromType(AddressType); + + if (!AddrLen) + return 0; + + AddrLen += sizeof(ULONG) + 2 * sizeof(USHORT); + AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); + return AddrLen; } @@ -58,9 +78,15 @@ VOID TaCopyAddressInPlace( PTA_ADDRESS Target, PTA_ADDRESS TaCopyAddress( PTA_ADDRESS Source ) { UINT AddrLen = TaLengthOfAddress( Source ); - PVOID Buffer = ExAllocatePool( NonPagedPool, AddrLen ); + PVOID Buffer; + if (!AddrLen) + return NULL; + + Buffer = ExAllocatePool( NonPagedPool, AddrLen ); + if (Buffer) RtlCopyMemory( Buffer, Source, AddrLen ); + return Buffer; } @@ -74,8 +100,10 @@ PTRANSPORT_ADDRESS TaCopyTransportAddress( PTRANSPORT_ADDRESS OtherAddress ) { UINT AddrLen; PTRANSPORT_ADDRESS A; - ASSERT(OtherAddress->TAAddressCount == 1); AddrLen = TaLengthOfTransportAddress( OtherAddress ); + if (!AddrLen) + return NULL; + A = ExAllocatePool( NonPagedPool, AddrLen ); if( A ) @@ -84,20 +112,39 @@ PTRANSPORT_ADDRESS TaCopyTransportAddress( PTRANSPORT_ADDRESS OtherAddress ) { return A; } +NTSTATUS TdiBuildNullTransportAddressInPlace(PTRANSPORT_ADDRESS A, UINT AddressType) +{ + A->TAAddressCount = 1; + + A->Address[0].AddressLength = TdiAddressSizeFromType(AddressType); + if (!A->Address[0].AddressLength) + return STATUS_INVALID_PARAMETER; + + A->Address[0].AddressType = AddressType; + + RtlZeroMemory(A->Address[0].Address, A->Address[0].AddressLength); + + return STATUS_SUCCESS; +} + PTRANSPORT_ADDRESS TaBuildNullTransportAddress(UINT AddressType) { UINT AddrLen; PTRANSPORT_ADDRESS A; AddrLen = TaLengthOfTransportAddressByType(AddressType); + if (!AddrLen) + return NULL; + A = ExAllocatePool(NonPagedPool, AddrLen); if (A) { - A->TAAddressCount = 1; - A->Address[0].AddressLength = TdiAddressSizeFromType(AddressType); - A->Address[0].AddressType = AddressType; - RtlZeroMemory(A->Address[0].Address, A->Address[0].AddressLength); + if (TdiBuildNullTransportAddressInPlace(A, AddressType) != STATUS_SUCCESS) + { + ExFreePool(A); + return NULL; + } } return A; @@ -118,9 +165,12 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace ULONG TdiAddressSize; PTRANSPORT_ADDRESS TransportAddress; - TdiAddressSize = TdiAddressSizeFromType(Type); + TdiAddressSize = TaLengthOfTransportAddressByType(Type); if (!TdiAddressSize) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return STATUS_INVALID_PARAMETER; + } RtlZeroMemory(ConnInfo, sizeof(TDI_CONNECTION_INFORMATION) + @@ -130,10 +180,8 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace ConnInfo->RemoteAddressLength = TdiAddressSize; ConnInfo->RemoteAddress = TransportAddress = (PTRANSPORT_ADDRESS)&ConnInfo[1]; - TransportAddress->TAAddressCount = 1; - TransportAddress->Address[0].AddressType = Type; - return STATUS_SUCCESS; + return TdiBuildNullTransportAddressInPlace(TransportAddress, Type); } NTSTATUS TdiBuildNullConnectionInfo @@ -153,8 +201,9 @@ NTSTATUS TdiBuildNullConnectionInfo ULONG TdiAddressSize; NTSTATUS Status; - TdiAddressSize = TdiAddressSizeFromType(Type); + TdiAddressSize = TaLengthOfTransportAddressByType(Type); if (!TdiAddressSize) { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); *ConnectionInfo = NULL; return STATUS_INVALID_PARAMETER; } @@ -170,15 +219,13 @@ NTSTATUS TdiBuildNullConnectionInfo Status = TdiBuildNullConnectionInfoInPlace( ConnInfo, Type ); - if (!NT_SUCCESS(Status)) { + if (!NT_SUCCESS(Status)) + { ExFreePool( ConnInfo ); - *ConnectionInfo = NULL; - return Status; - } else - *ConnectionInfo = ConnInfo; + ConnInfo = NULL; + } - ConnInfo->RemoteAddress = (PTA_ADDRESS)&ConnInfo[1]; - ConnInfo->RemoteAddressLength = TdiAddressSize; + *ConnectionInfo = ConnInfo; return Status; } @@ -215,60 +262,3 @@ TdiBuildConnectionInfo return Status; } -NTSTATUS -TdiBuildConnectionInfoPair -( PTDI_CONNECTION_INFO_PAIR ConnectionInfo, - PTRANSPORT_ADDRESS From, PTRANSPORT_ADDRESS To ) -/* - * FUNCTION: Fill a TDI_CONNECTION_INFO_PAIR struct will the two addresses - * given. - * ARGUMENTS: - * ConnectionInfo: The pair - * From: The from address - * To: The to address - * RETURNS: - * Status of the operation - */ -{ - PCHAR LayoutFrame; - UINT SizeOfEntry; - ULONG TdiAddressSize; - PTDI_CONNECTION_INFORMATION FromTdiConn, ToTdiConn; - - if (!From) return STATUS_INVALID_PARAMETER; - - /* FIXME: Get from socket information */ - TdiAddressSize = TdiAddressSizeFromType(From->Address[0].AddressType); - if (!TdiAddressSize) - return STATUS_INVALID_PARAMETER; - - SizeOfEntry = TdiAddressSize + sizeof(TDI_CONNECTION_INFORMATION); - - LayoutFrame = (PCHAR)ExAllocatePool(NonPagedPool, 2 * SizeOfEntry); - - if (!LayoutFrame) { - AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory( LayoutFrame, 2 * SizeOfEntry ); - - FromTdiConn = (PTDI_CONNECTION_INFORMATION)LayoutFrame; - ToTdiConn = (PTDI_CONNECTION_INFORMATION)LayoutFrame + SizeOfEntry; - - TdiBuildConnectionInfoInPlace( FromTdiConn, From ); - - TdiBuildConnectionInfoInPlace( ToTdiConn, To ); - - return STATUS_SUCCESS; -} - -PTA_ADDRESS TdiGetRemoteAddress( PTDI_CONNECTION_INFORMATION TdiConn ) -/* - * Convenience function that rounds out the abstraction of - * the TDI_CONNECTION_INFORMATION struct. - */ -{ - return TdiConn->RemoteAddress; -} - diff --git a/drivers/network/afd/afd/write.c b/drivers/network/afd/afd/write.c index ef01dd0a8da..c6e9591a8c6 100644 --- a/drivers/network/afd/afd/write.c +++ b/drivers/network/afd/afd/write.c @@ -8,9 +8,6 @@ * 20040708 Created */ #include "afd.h" -#include "tdi_proto.h" -#include "tdiconn.h" -#include "debug.h" static NTSTATUS NTAPI SendComplete ( PDEVICE_OBJECT DeviceObject, @@ -179,7 +176,8 @@ static NTSTATUS NTAPI SendComplete break; } - if (FCB->Send.Size - FCB->Send.BytesUsed != 0) + if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && + !FCB->SendClosed) { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; @@ -299,8 +297,11 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress ) + { + AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); + } if( !(SendReq = LockRequest( Irp, IrpSp )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); @@ -319,6 +320,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); if( NT_SUCCESS(Status) ) { + FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); @@ -347,24 +349,28 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, } } - if (FCB->DisconnectPending && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE)) + if (FCB->PollState & AFD_EVENT_CLOSE) { - /* We're pending a send shutdown so don't accept anymore sends */ - return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); + AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); + + /* This is an unexpected remote disconnect */ + return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } - if (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT)) + if (FCB->PollState & AFD_EVENT_ABORT) { - if (FCB->PollStatus[FD_CLOSE_BIT] == STATUS_SUCCESS) - { - /* This is a local send shutdown or a graceful remote disconnect */ - return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); - } - else - { - /* This is an unexpected remote disconnect */ - return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); - } + AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); + + /* This is an abortive socket closure on our side */ + return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); + } + + if (FCB->SendClosed) + { + AFD_DbgPrint(MIN_TRACE,("No more sends\n")); + + /* This is a graceful send closure */ + return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(SendReq = LockRequest( Irp, IrpSp )) ) @@ -433,6 +439,8 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, SpaceAvail -= SendReq->BufferArray[i].len; } + FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; + if( TotalBytesCopied == 0 ) { AFD_DbgPrint(MID_TRACE,("Empty send\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); @@ -503,8 +511,11 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND && FCB->State != SOCKET_STATE_CREATED) + { + AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); return UnlockAndMaybeComplete ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); + } if( !(SendReq = LockRequest( Irp, IrpSp )) ) return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); @@ -550,6 +561,7 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Check the size of the Address given ... */ if( NT_SUCCESS(Status) ) { + FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); diff --git a/drivers/network/afd/include/afd.h b/drivers/network/afd/include/afd.h index aa9bcff6cea..04464ffff26 100644 --- a/drivers/network/afd/include/afd.h +++ b/drivers/network/afd/include/afd.h @@ -28,6 +28,11 @@ #include #include #include +#include + +#include "tdi_proto.h" +#include "tdiconn.h" +#include "debug.h" #ifndef MIN #define MIN(x,y) (((x)<(y))?(x):(y)) @@ -103,7 +108,7 @@ typedef struct IPADDR_ENTRY { #define FUNCTION_CLOSE 6 #define MAX_FUNCTIONS 7 -#define IN_FLIGHT_REQUESTS 4 +#define IN_FLIGHT_REQUESTS 5 #define EXTRA_LOCK_BUFFERS 2 /* Number of extra buffers needed * for ancillary data on packet @@ -173,7 +178,7 @@ typedef struct _AFD_STORED_DATAGRAM { } AFD_STORED_DATAGRAM, *PAFD_STORED_DATAGRAM; typedef struct _AFD_FCB { - BOOLEAN Locked, Critical, Overread, NonBlocking, OobInline; + BOOLEAN Locked, Critical, Overread, NonBlocking, OobInline, TdiReceiveClosed, SendClosed; UINT State, Flags, GroupID, GroupType; KIRQL OldIrql; UINT LockCount; @@ -193,6 +198,7 @@ typedef struct _AFD_FCB { KMUTEX Mutex; PKEVENT EventSelect; DWORD EventSelectTriggers; + DWORD EventSelectDisabled; UNICODE_STRING TdiDeviceName; PVOID Context; DWORD PollState; @@ -315,6 +321,7 @@ VOID DestroySocket( PAFD_FCB FCB ); VOID NTAPI AfdCancelHandler(PDEVICE_OBJECT DeviceObject, PIRP Irp); VOID RetryDisconnectCompletion(PAFD_FCB FCB); +BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp); /* read.c */ diff --git a/drivers/network/afd/include/tdiconn.h b/drivers/network/afd/include/tdiconn.h index c06d930b2da..1eb94a33d4c 100644 --- a/drivers/network/afd/include/tdiconn.h +++ b/drivers/network/afd/include/tdiconn.h @@ -24,8 +24,3 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace ( PTDI_CONNECTION_INFORMATION ConnInfo, ULONG Type ); NTSTATUS TdiBuildNullConnectionInfo ( PTDI_CONNECTION_INFORMATION *ConnectionInfo, ULONG Type ); -NTSTATUS TdiBuildConnectionInfoPair -( PTDI_CONNECTION_INFO_PAIR ConnectionInfo, - PTRANSPORT_ADDRESS From, - PTRANSPORT_ADDRESS To ); -PTA_ADDRESS TdiGetRemoteAddress( PTDI_CONNECTION_INFORMATION TdiConn ); diff --git a/drivers/network/dd/ne2000/CMakeLists.txt b/drivers/network/dd/ne2000/CMakeLists.txt index f11ebe95a9b..32c2d8b01af 100644 --- a/drivers/network/dd/ne2000/CMakeLists.txt +++ b/drivers/network/dd/ne2000/CMakeLists.txt @@ -7,8 +7,7 @@ list(APPEND SOURCE ne2000.rc) add_library(ne2000 SHARED ${SOURCE}) - +add_pch(ne2000 include/ne2000.h) set_module_type(ne2000 kernelmodedriver) add_importlibs(ne2000 ndis ntoskrnl hal) - add_cd_file(TARGET ne2000 DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/network/dd/ne2000/include/ne2000.h b/drivers/network/dd/ne2000/include/ne2000.h index 4c4e28bdbcd..3acb69bfa7d 100644 --- a/drivers/network/dd/ne2000/include/ne2000.h +++ b/drivers/network/dd/ne2000/include/ne2000.h @@ -5,8 +5,6 @@ * PURPOSE: NE2000 driver definitions */ -#pragma once - #define NDIS_MINIPORT_DRIVER 1 #define NDIS_LEGACY_MINIPORT 1 #define NDIS51_MINIPORT 1 diff --git a/drivers/network/dd/ne2000/ne2000/8390.c b/drivers/network/dd/ne2000/ne2000/8390.c index 03adcab94bf..3ef4f911d6b 100644 --- a/drivers/network/dd/ne2000/ne2000/8390.c +++ b/drivers/network/dd/ne2000/ne2000/8390.c @@ -8,7 +8,6 @@ * CSH 27/08-2000 Created */ #include -#include /* Null-terminated array of ports to probe. This is "semi-risky" (Don Becker). */ ULONG_PTR ProbeAddressList[] = { 0x280, 0x300, 0x320, 0x340, 0x360, 0x380, 0 }; diff --git a/drivers/network/dd/ne2000/ne2000/main.c b/drivers/network/dd/ne2000/ne2000/main.c index 626b5763d99..09cf47386ac 100644 --- a/drivers/network/dd/ne2000/ne2000/main.c +++ b/drivers/network/dd/ne2000/ne2000/main.c @@ -8,7 +8,6 @@ * CSH 27/08-2000 Created */ #include -#include NTSTATUS NTAPI diff --git a/drivers/network/dd/pcnet/CMakeLists.txt b/drivers/network/dd/pcnet/CMakeLists.txt index 7235782f5e0..b1a513667e8 100644 --- a/drivers/network/dd/pcnet/CMakeLists.txt +++ b/drivers/network/dd/pcnet/CMakeLists.txt @@ -11,8 +11,7 @@ list(APPEND SOURCE pcnet.rc) add_library(pcnet SHARED ${SOURCE}) - +add_pch(pcnet pcnet.h) set_module_type(pcnet kernelmodedriver) add_importlibs(pcnet ndis ntoskrnl hal) - add_cd_file(TARGET pcnet DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/network/dd/pcnet/pcnet.c b/drivers/network/dd/pcnet/pcnet.c index 6aca85bbbf2..c5b39f32742 100644 --- a/drivers/network/dd/pcnet/pcnet.c +++ b/drivers/network/dd/pcnet/pcnet.c @@ -38,9 +38,6 @@ * - this assumes a 32-bit machine */ -#include -#include "pci.h" -#include "pcnethw.h" #include "pcnet.h" #define NDEBUG diff --git a/drivers/network/dd/pcnet/pcnet.h b/drivers/network/dd/pcnet/pcnet.h index 1a23ba53ec6..b1082e4c872 100644 --- a/drivers/network/dd/pcnet/pcnet.h +++ b/drivers/network/dd/pcnet/pcnet.h @@ -25,7 +25,9 @@ * - this assumes 32-bit physical addresses */ -#pragma once +#include +#include "pci.h" +#include "pcnethw.h" /* statistics struct */ typedef struct _ADAPTER_STATS diff --git a/drivers/network/dd/pcnet/requests.c b/drivers/network/dd/pcnet/requests.c index 43ad68f0518..79faee5d14e 100644 --- a/drivers/network/dd/pcnet/requests.c +++ b/drivers/network/dd/pcnet/requests.c @@ -33,8 +33,6 @@ * necessary. */ -#include -#include "pcnethw.h" #include "pcnet.h" #define NDEBUG diff --git a/drivers/network/ndis/include/ndissys.h b/drivers/network/ndis/include/ndissys.h index 10c6a26ede4..4eedf3dacd5 100644 --- a/drivers/network/ndis/include/ndissys.h +++ b/drivers/network/ndis/include/ndissys.h @@ -21,6 +21,7 @@ #include "miniport.h" #include "protocol.h" +#include "efilter.h" #include "buffer.h" /* Exported functions */ diff --git a/drivers/network/ndis/ndis/efilter.c b/drivers/network/ndis/ndis/efilter.c index 0a4194dff32..bbde5bdc7be 100644 --- a/drivers/network/ndis/ndis/efilter.c +++ b/drivers/network/ndis/ndis/efilter.c @@ -10,7 +10,6 @@ */ #include "ndissys.h" -#include "efilter.h" BOOLEAN NTAPI diff --git a/drivers/network/ndis/ndis/miniport.c b/drivers/network/ndis/ndis/miniport.c index 1c189b92477..c5e9e6fb43c 100644 --- a/drivers/network/ndis/ndis/miniport.c +++ b/drivers/network/ndis/ndis/miniport.c @@ -12,9 +12,6 @@ */ #include "ndissys.h" -#include "efilter.h" - -#include /* * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper diff --git a/drivers/network/ndis/ndis/protocol.c b/drivers/network/ndis/ndis/protocol.c index f41017b1035..b8b54eddcfd 100644 --- a/drivers/network/ndis/ndis/protocol.c +++ b/drivers/network/ndis/ndis/protocol.c @@ -11,7 +11,6 @@ */ #include "ndissys.h" -#include #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" #define LINKAGE_KEY L"\\Linkage" @@ -908,20 +907,22 @@ ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PPROTOCOL_BINDING Protoc */ OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING RegistryPath; - WCHAR *RegistryPathStr; + WCHAR *RegistryPathStr, *DataPtr = NULL; NTSTATUS NtStatus; - WCHAR *DataPtr; HANDLE DriverKeyHandle = NULL; PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL; PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics = &Protocol->Chars; + UNICODE_STRING ValueName; + ULONG ResultLength; + PLIST_ENTRY CurrentEntry = NULL; RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__); if(!RegistryPathStr) - { + { NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); *Status = NDIS_STATUS_RESOURCES; return; - } + } wcscpy(RegistryPathStr, SERVICES_KEY); wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR)); @@ -936,130 +937,165 @@ ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PPROTOCOL_BINDING Protoc ExFreePool(RegistryPathStr); - if(!NT_SUCCESS(NtStatus)) - { - NDIS_DbgPrint(MIN_TRACE, ("Unable to open protocol configuration\n")); - *Status = NDIS_STATUS_FAILURE; - return; - } - - NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n")); + if(NT_SUCCESS(NtStatus)) + { + NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n")); - { - UNICODE_STRING ValueName; - ULONG ResultLength; + RtlInitUnicodeString(&ValueName, L"Bind"); - RtlInitUnicodeString(&ValueName, L"Bind"); + NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength); + if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS) + { + NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n")); + ZwClose(DriverKeyHandle); + } + else + { + KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__); + if(!KeyInformation) + { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + ZwClose(DriverKeyHandle); + NtStatus = STATUS_NO_MEMORY; + } + else + { + NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation, + sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength); - NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength); - if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS) - { - NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n")); - ZwClose(DriverKeyHandle); - *Status = NDIS_STATUS_FAILURE; - return; - } + ZwClose(DriverKeyHandle); - KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__); - if(!KeyInformation) - { - NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); - ZwClose(DriverKeyHandle); - *Status = NDIS_STATUS_FAILURE; - return; - } + if(!NT_SUCCESS(NtStatus)) + { + NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n")); + ExFreePool(KeyInformation); + KeyInformation = NULL; + } + } + } + } - NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation, - sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength); + if (!NT_SUCCESS(NtStatus)) + { + NDIS_DbgPrint(MIN_TRACE, ("Performing global bind for protocol '%wZ'\n", &ProtocolCharacteristics->Name)); + KeyInformation = NULL; - ZwClose(DriverKeyHandle); + CurrentEntry = AdapterListHead.Flink; + } + else + { + NDIS_DbgPrint(MIN_TRACE, ("Performing standard bind for protocol '%wZ'\n", &ProtocolCharacteristics->Name)); - if(!NT_SUCCESS(NtStatus)) - { - NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n")); - ExFreePool(KeyInformation); - *Status = NDIS_STATUS_FAILURE; - return; - } - } + DataPtr = (WCHAR*)KeyInformation->Data; + } - /* Assume success for now */ - *Status = NDIS_STATUS_SUCCESS; + /* Assume success for now */ + *Status = NDIS_STATUS_SUCCESS; - for (DataPtr = (WCHAR *)KeyInformation->Data; - *DataPtr != 0; - DataPtr += wcslen(DataPtr) + 1) + while (TRUE) { - /* BindContext is for tracking pending binding operations */ - VOID *BindContext = 0; - NDIS_STRING DeviceName; - NDIS_STRING RegistryPath; - WCHAR *RegistryPathStr = NULL; - ULONG PathLength = 0; + /* BindContext is for tracking pending binding operations */ + VOID *BindContext = 0; + NDIS_STRING DeviceName; + NDIS_STRING RegistryPath; + WCHAR *RegistryPathStr = NULL; + ULONG PathLength = 0; + PLOGICAL_ADAPTER Adapter; + + if (KeyInformation) + { + /* Parse the REG_MULTI_SZ entry for device names */ + if (!(*DataPtr)) + break; - RtlInitUnicodeString(&DeviceName, DataPtr); /* we know this is 0-term */ + RtlInitUnicodeString(&DeviceName, DataPtr); + } + else + { + /* Use the device name from the global adapter list */ + if (CurrentEntry == &AdapterListHead) + break; - /* Make sure the adapter has started */ - if (!MiniLocateDevice(&DeviceName)) - { - /* It wasn't in the global miniport list, so skip the bind entry */ - continue; - } + Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry); - /* Make sure this device isn't already bound to this protocol */ - if (LocateAdapterBindingByName(Protocol, &DeviceName)) - { - /* It was already in this protocol's bound adapter list, so skip the bind entry */ - continue; - } + DeviceName = Adapter->NdisMiniportBlock.MiniportName; + } - /* - * RegistryPath should be: - * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip - * - * This is constructed as follows: - * SERVICES_KEY + extracted device name + Protocol name from characteristics - */ - - PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */ - wcslen( DataPtr + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */ - sizeof(PARAMETERS_KEY) + /* \Parameters\ */ - ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */ - - RegistryPathStr = ExAllocatePool(PagedPool, PathLength); - if(!RegistryPathStr) + /* Make sure the adapter has started */ + if (!MiniLocateDevice(&DeviceName)) { - NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n")); - ExFreePool(KeyInformation); - *Status = NDIS_STATUS_RESOURCES; - return; + /* It wasn't in the global miniport list, so skip the bind entry */ + goto next; + } + + /* Make sure this device isn't already bound to this protocol */ + if (LocateAdapterBindingByName(Protocol, &DeviceName)) + { + /* It was already in this protocol's bound adapter list, so skip the bind entry */ + goto next; + } + + /* + * RegistryPath should be: + * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip + * + * This is constructed as follows: + * SERVICES_KEY + extracted device name + Protocol name from characteristics + */ + + PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */ + wcslen( DeviceName.Buffer + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */ + sizeof(PARAMETERS_KEY) + /* \Parameters\ */ + ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */ + + RegistryPathStr = ExAllocatePool(PagedPool, PathLength); + if(!RegistryPathStr) + { + NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n")); + *Status = NDIS_STATUS_RESOURCES; + break; } - wcscpy(RegistryPathStr, SERVICES_KEY); - wcscat(RegistryPathStr, DataPtr + 8 ); - wcscat(RegistryPathStr, PARAMETERS_KEY); - wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) ); + wcscpy(RegistryPathStr, SERVICES_KEY); + wcscat(RegistryPathStr, DeviceName.Buffer + 8 ); + wcscat(RegistryPathStr, PARAMETERS_KEY); + wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) ); - RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0; + RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0; - RtlInitUnicodeString(&RegistryPath, RegistryPathStr); + RtlInitUnicodeString(&RegistryPath, RegistryPathStr); - NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n", - &DeviceName, &RegistryPath)); + NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n", + &DeviceName, &RegistryPath)); { - BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler; - if(BindHandler) - { - BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0); - NDIS_DbgPrint(MIN_TRACE, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics->Name, *Status, &DeviceName)); - } - else - NDIS_DbgPrint(MIN_TRACE, ("No protocol bind handler specified\n")); + BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler; + if(BindHandler) + { + BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0); + NDIS_DbgPrint(MIN_TRACE, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics->Name, *Status, &DeviceName)); + } + else + NDIS_DbgPrint(MIN_TRACE, ("No protocol bind handler specified\n")); + } + + next: + if (KeyInformation) + { + /* Advance to the next adapter in the REG_MULTI_SZ */ + DataPtr += (DeviceName.Length / sizeof(WCHAR)) + 1; + } + else + { + /* Advance to the next adapter in the global list */ + CurrentEntry = CurrentEntry->Flink; } } - ExFreePool(KeyInformation); + if (KeyInformation) + { + ExFreePool(KeyInformation); + } } /* diff --git a/drivers/network/tcpip/include/precomp.h b/drivers/network/tcpip/include/precomp.h index 124df675e7d..bd3ef374172 100644 --- a/drivers/network/tcpip/include/precomp.h +++ b/drivers/network/tcpip/include/precomp.h @@ -33,3 +33,4 @@ #include #include #include +#include \ No newline at end of file diff --git a/drivers/network/tcpip/tcpip/dispatch.c b/drivers/network/tcpip/tcpip/dispatch.c index d42c4fed217..75c1cfba41d 100644 --- a/drivers/network/tcpip/tcpip/dispatch.c +++ b/drivers/network/tcpip/tcpip/dispatch.c @@ -10,8 +10,6 @@ */ #include "precomp.h" -#include - NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status ) { KIRQL OldIrql; @@ -555,14 +553,22 @@ NTSTATUS DispTdiDisconnect( Status = STATUS_INVALID_PARAMETER; goto done; } + + Status = DispPrepareIrpForCancel + (TranContext->Handle.ConnectionContext, + Irp, + (PDRIVER_CANCEL)DispCancelRequest); - Status = TCPDisconnect( - TranContext->Handle.ConnectionContext, - DisReq->RequestFlags, - DisReq->RequestConnectionInformation, - DisReq->ReturnConnectionInformation, - DispDataRequestComplete, - Irp ); + if (NT_SUCCESS(Status)) + { + Status = TCPDisconnect(TranContext->Handle.ConnectionContext, + DisReq->RequestFlags, + DisReq->RequestSpecific, + DisReq->RequestConnectionInformation, + DisReq->ReturnConnectionInformation, + DispDataRequestComplete, + Irp); + } done: if (Status != STATUS_PENDING) { diff --git a/drivers/network/tcpip/tcpip/info.c b/drivers/network/tcpip/tcpip/info.c index 4e11d9aa122..6970615e610 100644 --- a/drivers/network/tcpip/tcpip/info.c +++ b/drivers/network/tcpip/tcpip/info.c @@ -10,7 +10,6 @@ #include "precomp.h" #include -#include VOID AddEntity(ULONG EntityType, PVOID Context, ULONG Flags) { diff --git a/drivers/network/tcpip/tcpip/main.c b/drivers/network/tcpip/tcpip/main.c index ad08ac729cd..034b9df2d0b 100644 --- a/drivers/network/tcpip/tcpip/main.c +++ b/drivers/network/tcpip/tcpip/main.c @@ -680,14 +680,14 @@ DriverEntry( EntityMax = MAX_TDI_ENTITIES; /* Allocate NDIS packet descriptors */ - NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT)); + NdisAllocatePacketPoolEx(&NdisStatus, &GlobalPacketPool, 500, 1500, sizeof(PACKET_CONTEXT)); if (NdisStatus != NDIS_STATUS_SUCCESS) { TiUnload(DriverObject); return STATUS_INSUFFICIENT_RESOURCES; } /* Allocate NDIS buffer descriptors */ - NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100); + NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 2000); if (NdisStatus != NDIS_STATUS_SUCCESS) { TiUnload(DriverObject); return STATUS_INSUFFICIENT_RESOURCES; diff --git a/drivers/network/tdi/CMakeLists.txt b/drivers/network/tdi/CMakeLists.txt index eeb5b468c0c..f8b6a74cf25 100644 --- a/drivers/network/tdi/CMakeLists.txt +++ b/drivers/network/tdi/CMakeLists.txt @@ -23,8 +23,7 @@ list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/tdi.def) add_library(tdi SHARED ${SOURCE}) - +add_pch(tdi precomp.h) set_module_type(tdi kernelmodedriver) add_importlibs(tdi ntoskrnl hal) - add_cd_file(TARGET tdi DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/network/tdi/cte/events.c b/drivers/network/tdi/cte/events.c index dd6aff158e3..26bf227d77f 100644 --- a/drivers/network/tdi/cte/events.c +++ b/drivers/network/tdi/cte/events.c @@ -8,7 +8,7 @@ /* INCLUDES *****************************************************************/ -#include +#include "precomp.h" typedef struct _CTEBLOCK_EVENT { diff --git a/drivers/network/tdi/cte/string.c b/drivers/network/tdi/cte/string.c index bd5aa52ac49..2f28750548e 100644 --- a/drivers/network/tdi/cte/string.c +++ b/drivers/network/tdi/cte/string.c @@ -1,7 +1,7 @@ /* $Id$ * */ -#include +#include "precomp.h" /* * @unimplemented diff --git a/drivers/network/tdi/cte/timer.c b/drivers/network/tdi/cte/timer.c index aa82dfe1455..979390e1557 100644 --- a/drivers/network/tdi/cte/timer.c +++ b/drivers/network/tdi/cte/timer.c @@ -8,7 +8,7 @@ /* INCLUDES *****************************************************************/ -#include +#include "precomp.h" /* FIXME: Move to a common header! */ struct _CTE_DELAYED_EVENT; diff --git a/drivers/network/tdi/misc/main.c b/drivers/network/tdi/misc/main.c index d66341c8dd9..bcbf6ed8cd3 100644 --- a/drivers/network/tdi/misc/main.c +++ b/drivers/network/tdi/misc/main.c @@ -2,7 +2,7 @@ * DESCRIPTION: Entry point for TDI.SYS * (c) Captain Obvious */ -#include +#include "precomp.h" extern LONG CteTimeIncrement; diff --git a/drivers/network/tdi/precomp.h b/drivers/network/tdi/precomp.h new file mode 100644 index 00000000000..00a2b729591 --- /dev/null +++ b/drivers/network/tdi/precomp.h @@ -0,0 +1,3 @@ +#include +#include +#include diff --git a/drivers/network/tdi/tdi/dereg.c b/drivers/network/tdi/tdi/dereg.c index 787b3e63c7e..4a7cfcc4ae9 100644 --- a/drivers/network/tdi/tdi/dereg.c +++ b/drivers/network/tdi/tdi/dereg.c @@ -1,5 +1,4 @@ -#include -#include +#include "precomp.h" /* De-/Register Action IDs for TdiDeRegister */ diff --git a/drivers/network/tdi/tdi/handler.c b/drivers/network/tdi/tdi/handler.c index 575edebe63e..fe24d0b1f5d 100644 --- a/drivers/network/tdi/tdi/handler.c +++ b/drivers/network/tdi/tdi/handler.c @@ -2,9 +2,7 @@ * * DESCRIPTION: Default TDI event handlers. */ -#include -#include - +#include "precomp.h" /* * ClientEventChainedReceiveDatagram diff --git a/drivers/network/tdi/tdi/obsolete.c b/drivers/network/tdi/tdi/obsolete.c index f2e143123cb..42c3935cea6 100644 --- a/drivers/network/tdi/tdi/obsolete.c +++ b/drivers/network/tdi/tdi/obsolete.c @@ -2,7 +2,7 @@ * */ -#include +#include "precomp.h" /* * @unimplemented @@ -10,7 +10,7 @@ VOID NTAPI TdiMapBuffer ( - ULONG Unknown0 + IN PMDL MdlChain ) { /* This function is absolete */ @@ -23,7 +23,7 @@ TdiMapBuffer ( VOID NTAPI TdiUnmapBuffer ( - ULONG Unknown0 + IN PMDL MdlChain ) { /* This function is obsolete */ diff --git a/drivers/network/tdi/tdi/stubs.c b/drivers/network/tdi/tdi/stubs.c index 0396d83d455..8af72d8bb85 100644 --- a/drivers/network/tdi/tdi/stubs.c +++ b/drivers/network/tdi/tdi/stubs.c @@ -2,8 +2,7 @@ /* $Id$ * */ -#include -#include +#include "precomp.h" /* * @unimplemented diff --git a/drivers/serial/serenum/CMakeLists.txt b/drivers/serial/serenum/CMakeLists.txt index c31039222fe..770a652e00d 100644 --- a/drivers/serial/serenum/CMakeLists.txt +++ b/drivers/serial/serenum/CMakeLists.txt @@ -7,7 +7,7 @@ add_library(serenum SHARED serenum.c serenum.rc) +add_pch(serenum serenum.h) set_module_type(serenum kernelmodedriver) add_importlibs(serenum ntoskrnl hal) - add_cd_file(TARGET serenum DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/serial/serenum/misc.c b/drivers/serial/serenum/misc.c index c3a9d1b144d..033bd8b893f 100644 --- a/drivers/serial/serenum/misc.c +++ b/drivers/serial/serenum/misc.c @@ -8,7 +8,6 @@ */ #include "serenum.h" -#include static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion; diff --git a/drivers/serial/serenum/serenum.h b/drivers/serial/serenum/serenum.h index 481442361a8..0601b44a0ce 100644 --- a/drivers/serial/serenum/serenum.h +++ b/drivers/serial/serenum/serenum.h @@ -11,6 +11,7 @@ #include #include #include +#include #include typedef enum diff --git a/drivers/serial/serial/CMakeLists.txt b/drivers/serial/serial/CMakeLists.txt index 68ec42d9b40..6bea2c8c9c7 100644 --- a/drivers/serial/serial/CMakeLists.txt +++ b/drivers/serial/serial/CMakeLists.txt @@ -14,7 +14,7 @@ add_library(serial SHARED serial.c serial.rc) +add_pch(serial serial.h) set_module_type(serial kernelmodedriver) add_importlibs(serial ntoskrnl hal) - add_cd_file(TARGET serial DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/serial/serial/pnp.c b/drivers/serial/serial/pnp.c index 8578c22da98..8ecabdc3cbd 100644 --- a/drivers/serial/serial/pnp.c +++ b/drivers/serial/serial/pnp.c @@ -24,8 +24,6 @@ SerialAddDeviceInternal( NTSTATUS Status; WCHAR DeviceNameBuffer[32]; UNICODE_STRING DeviceName; - static ULONG DeviceNumber = 0; - static ULONG ComPortNumber = 1; TRACE_(SERIAL, "SerialAddDeviceInternal()\n"); @@ -33,7 +31,7 @@ SerialAddDeviceInternal( ASSERT(Pdo); /* Create new device object */ - swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", DeviceNumber); + swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", IoGetConfigurationInformation()->SerialCount); RtlInitUnicodeString(&DeviceName, DeviceNameBuffer); Status = IoCreateDevice(DriverObject, sizeof(SERIAL_DEVICE_EXTENSION), @@ -59,9 +57,9 @@ SerialAddDeviceInternal( goto ByeBye; } - DeviceExtension->SerialPortNumber = DeviceNumber++; + DeviceExtension->SerialPortNumber = IoGetConfigurationInformation()->SerialCount++; if (pComPortNumber == NULL) - DeviceExtension->ComPort = ComPortNumber++; + DeviceExtension->ComPort = DeviceExtension->SerialPortNumber + 1; else DeviceExtension->ComPort = *pComPortNumber; DeviceExtension->Pdo = Pdo; diff --git a/drivers/setup/blue/CMakeLists.txt b/drivers/setup/blue/CMakeLists.txt index ae3c8f674be..a965797d46a 100644 --- a/drivers/setup/blue/CMakeLists.txt +++ b/drivers/setup/blue/CMakeLists.txt @@ -3,7 +3,7 @@ include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers) add_library(blue SHARED blue.c font.c blue.rc) +add_pch(blue blue.h) set_module_type(blue kernelmodedriver) add_importlibs(blue ntoskrnl hal) - add_cd_file(TARGET blue DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/setup/blue/blue.c b/drivers/setup/blue/blue.c index aab1cb03d97..f7a71f7d4a6 100644 --- a/drivers/setup/blue/blue.c +++ b/drivers/setup/blue/blue.c @@ -10,14 +10,6 @@ /* INCLUDES ******************************************************************/ -#include -#include -#define WINBASEAPI -typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES; - -#include -#include -#include //#include #include "blue.h" diff --git a/drivers/setup/blue/blue.h b/drivers/setup/blue/blue.h index 49be79abab7..988031c2b26 100644 --- a/drivers/setup/blue/blue.h +++ b/drivers/setup/blue/blue.h @@ -8,6 +8,15 @@ /* DEFINITIONS ***************************************************************/ +#include +#include + +typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES; +#include + +#include +#include + #include #include #include diff --git a/drivers/storage/class/cdrom/CMakeLists.txt b/drivers/storage/class/cdrom/CMakeLists.txt index 3a21ad923b3..af0557833a7 100644 --- a/drivers/storage/class/cdrom/CMakeLists.txt +++ b/drivers/storage/class/cdrom/CMakeLists.txt @@ -10,4 +10,5 @@ add_importlibs(cdrom ntoskrnl hal) +add_pch(cdrom precomp.h) add_cd_file(TARGET cdrom DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/storage/class/cdrom/cdrom.c b/drivers/storage/class/cdrom/cdrom.c index 12531ba3a4d..bc2f259b576 100644 --- a/drivers/storage/class/cdrom/cdrom.c +++ b/drivers/storage/class/cdrom/cdrom.c @@ -6,13 +6,7 @@ * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK */ -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" //#define NDEBUG #include diff --git a/drivers/storage/class/cdrom/findscsi.c b/drivers/storage/class/cdrom/findscsi.c index 3df16216c91..6b0cab655be 100644 --- a/drivers/storage/class/cdrom/findscsi.c +++ b/drivers/storage/class/cdrom/findscsi.c @@ -6,13 +6,7 @@ * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK */ -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" //#define NDEBUG #include diff --git a/drivers/storage/class/cdrom/precomp.h b/drivers/storage/class/cdrom/precomp.h new file mode 100644 index 00000000000..e1d5878ae1e --- /dev/null +++ b/drivers/storage/class/cdrom/precomp.h @@ -0,0 +1,7 @@ +#include +#include +#include +#include +#include +#include +#include diff --git a/drivers/storage/classpnp/CMakeLists.txt b/drivers/storage/classpnp/CMakeLists.txt index 2c7c15e1e4d..1d5672b34b6 100644 --- a/drivers/storage/classpnp/CMakeLists.txt +++ b/drivers/storage/classpnp/CMakeLists.txt @@ -38,9 +38,8 @@ list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/class.def) add_library(classpnp SHARED ${SOURCE}) +add_pch(classpnp classp.h) target_link_libraries(classpnp ${PSEH_LIB} libcntpr) - set_module_type(classpnp kernelmodedriver) add_importlibs(classpnp hal ntoskrnl) - add_cd_file(TARGET classpnp DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/storage/classpnp/classp.h b/drivers/storage/classpnp/classp.h index 43dc218a309..a7298324694 100644 --- a/drivers/storage/classpnp/classp.h +++ b/drivers/storage/classpnp/classp.h @@ -25,7 +25,6 @@ Revision History: --*/ - #include #include #include @@ -42,6 +41,8 @@ Revision History: #include #include +#include "wmistr.h" + extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[]; extern GUID ClassGuidQueryRegInfoEx; diff --git a/drivers/storage/classpnp/classwmi.c b/drivers/storage/classpnp/classwmi.c index bbd43a6999d..1589c599d20 100644 --- a/drivers/storage/classpnp/classwmi.c +++ b/drivers/storage/classpnp/classwmi.c @@ -21,17 +21,7 @@ Revision History: --*/ -#include "stddef.h" -#include "ntddk.h" -#include "scsi.h" - -#include "classpnp.h" - -#include "mountdev.h" - -#include - -#include "wmistr.h" +#include "classp.h" NTSTATUS ClassSystemControl( diff --git a/drivers/storage/classpnp/dictlib.c b/drivers/storage/classpnp/dictlib.c index 310b227e0f0..2ae614d6930 100644 --- a/drivers/storage/classpnp/dictlib.c +++ b/drivers/storage/classpnp/dictlib.c @@ -23,8 +23,7 @@ Revision History: --*/ -#include -#include +#include "classp.h" #define DICTIONARY_SIGNATURE 'dsig' diff --git a/drivers/storage/classpnp/power.c b/drivers/storage/classpnp/power.c index 26d4d0172c2..aae10d7279d 100644 --- a/drivers/storage/classpnp/power.c +++ b/drivers/storage/classpnp/power.c @@ -21,13 +21,8 @@ Revision History: --*/ -#include "stddef.h" -#include "ntddk.h" -#include "scsi.h" #include "classp.h" -#include - #define CLASS_TAG_POWER 'WLcS' NTSTATUS diff --git a/drivers/storage/floppy/CMakeLists.txt b/drivers/storage/floppy/CMakeLists.txt index 6a2954f1806..8222c16d9af 100644 --- a/drivers/storage/floppy/CMakeLists.txt +++ b/drivers/storage/floppy/CMakeLists.txt @@ -8,8 +8,7 @@ add_library(floppy SHARED floppy.rc) target_link_libraries(floppy csq) - +add_pch(floppy precomp.h) set_module_type(floppy kernelmodedriver) add_importlibs(floppy hal ntoskrnl) - add_cd_file(TARGET floppy DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/storage/floppy/csqrtns.c b/drivers/storage/floppy/csqrtns.c index e6b84257b03..f50b1a51a11 100644 --- a/drivers/storage/floppy/csqrtns.c +++ b/drivers/storage/floppy/csqrtns.c @@ -38,11 +38,7 @@ * that my lock choice is a spin lock. */ -#include -#include - -#include "floppy.h" -#include "csqrtns.h" +#include "precomp.h" /* Global CSQ struct that the CSQ functions initialize and use */ IO_CSQ Csq; diff --git a/drivers/storage/floppy/csqrtns.h b/drivers/storage/floppy/csqrtns.h index af6193faa1c..2c3d507f333 100644 --- a/drivers/storage/floppy/csqrtns.h +++ b/drivers/storage/floppy/csqrtns.h @@ -24,11 +24,7 @@ * 15-Feb-2004 vizzini - Created */ -#ifdef _MSC_VER #include -#else -#include -#endif /* * CSQ Stuff diff --git a/drivers/storage/floppy/floppy.c b/drivers/storage/floppy/floppy.c index dd4bc70deff..857a95b98c8 100644 --- a/drivers/storage/floppy/floppy.c +++ b/drivers/storage/floppy/floppy.c @@ -40,14 +40,7 @@ * TODO: Media detection based on sector 1 */ -#include -#include - -#include "floppy.h" -#include "hardware.h" -#include "csqrtns.h" -#include "ioctl.h" -#include "readwrite.h" +#include "precomp.h" /* * Global controller info structures. Each controller gets one. Since the system diff --git a/drivers/storage/floppy/hardware.c b/drivers/storage/floppy/hardware.c index b0780759240..2b22ec9630d 100644 --- a/drivers/storage/floppy/hardware.c +++ b/drivers/storage/floppy/hardware.c @@ -47,11 +47,7 @@ * I prefer bit fields, but they break endianness. */ -#include -#include - -#include "floppy.h" -#include "hardware.h" +#include "precomp.h" /* * Hardware Support Routines @@ -452,7 +448,10 @@ HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo) /* Is the equipment check flag set? Could be no disk in drive... */ if((Buffer[0] & SR0_EQUIPMENT_CHECK) == SR0_EQUIPMENT_CHECK) - INFO_(FLOPPY, "HwRecalibrateResult: Seeked to track 0 successfully, but EC is set; returning STATUS_SUCCESS anyway\n"); + { + WARN_(FLOPPY, "HwRecalibrateResult: Seeked to track 0 successfully, but EC is set; returning failure\n"); + return STATUS_UNSUCCESSFUL; + } return STATUS_SUCCESS; } diff --git a/drivers/storage/floppy/ioctl.c b/drivers/storage/floppy/ioctl.c index 7c1615c2376..1cb84322f67 100644 --- a/drivers/storage/floppy/ioctl.c +++ b/drivers/storage/floppy/ioctl.c @@ -31,13 +31,7 @@ * TODO: Implement format */ -#include -#include - -#include "floppy.h" -#include "hardware.h" -#include "csqrtns.h" -#include "ioctl.h" +#include "precomp.h" NTSTATUS NTAPI diff --git a/drivers/storage/floppy/precomp.h b/drivers/storage/floppy/precomp.h new file mode 100644 index 00000000000..c7238f804af --- /dev/null +++ b/drivers/storage/floppy/precomp.h @@ -0,0 +1,9 @@ +#include +#include + +#include "floppy.h" +#include "csqrtns.h" +#include "hardware.h" +#include "csqrtns.h" +#include "ioctl.h" +#include "readwrite.h" diff --git a/drivers/storage/floppy/readwrite.c b/drivers/storage/floppy/readwrite.c index e29d325cbba..bafc2916c80 100644 --- a/drivers/storage/floppy/readwrite.c +++ b/drivers/storage/floppy/readwrite.c @@ -52,13 +52,7 @@ * TODO: Figure out specify timings */ -#include -#include - -#include "floppy.h" -#include "csqrtns.h" -#include "hardware.h" -#include "readwrite.h" +#include "precomp.h" static IO_ALLOCATION_ACTION NTAPI diff --git a/drivers/storage/ide/pciidex/CMakeLists.txt b/drivers/storage/ide/pciidex/CMakeLists.txt index c3365ce51b9..15d9e173a7c 100644 --- a/drivers/storage/ide/pciidex/CMakeLists.txt +++ b/drivers/storage/ide/pciidex/CMakeLists.txt @@ -11,9 +11,8 @@ list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/pciidex.def) add_library(pciidex SHARED ${SOURCE}) - +add_pch(pciidex pciidex.h) set_module_type(pciidex kernelmodedriver) add_importlibs(pciidex ntoskrnl) - add_cd_file(TARGET pciidex DESTINATION reactos/system32/drivers NO_CAB FOR all) add_importlib_target(pciidex.spec) diff --git a/drivers/storage/ide/uniata/CMakeLists.txt b/drivers/storage/ide/uniata/CMakeLists.txt index e5efe908570..ab0e3ddb08e 100644 --- a/drivers/storage/ide/uniata/CMakeLists.txt +++ b/drivers/storage/ide/uniata/CMakeLists.txt @@ -1,5 +1,7 @@ -include_directories(inc) +include_directories( + BEFORE ${CMAKE_CURRENT_SOURCE_DIR} + inc) #add_definitions(-D_DEBUG) @@ -17,7 +19,7 @@ add_library(uniata SHARED idedma.rc ros_glue/ros_glue.cpp) +add_pch(uniata stdafx.h) set_module_type(uniata kernelmodedriver) add_importlibs(uniata scsiport ntoskrnl hal) - -add_cd_file(TARGET uniata DESTINATION reactos/system32/drivers NO_CAB FOR all) \ No newline at end of file +add_cd_file(TARGET uniata DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/storage/scsiport/CMakeLists.txt b/drivers/storage/scsiport/CMakeLists.txt index 2be2a018591..fd8dafb4956 100644 --- a/drivers/storage/scsiport/CMakeLists.txt +++ b/drivers/storage/scsiport/CMakeLists.txt @@ -8,10 +8,8 @@ list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/scsiport.def) add_library(scsiport SHARED ${SOURCE}) - +add_pch(scsiport precomp.h) set_module_type(scsiport kernelmodedriver) - add_importlibs(scsiport ntoskrnl hal) add_importlib_target(scsiport.spec) - add_cd_file(TARGET scsiport DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/storage/scsiport/precomp.h b/drivers/storage/scsiport/precomp.h new file mode 100644 index 00000000000..8cfb69e8948 --- /dev/null +++ b/drivers/storage/scsiport/precomp.h @@ -0,0 +1,10 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsiport_int.h" diff --git a/drivers/storage/scsiport/scsiport.c b/drivers/storage/scsiport/scsiport.c index 566df4fdc8b..6010772740a 100644 --- a/drivers/storage/scsiport/scsiport.c +++ b/drivers/storage/scsiport/scsiport.c @@ -27,22 +27,13 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" #ifndef NDEBUG #define NDEBUG #endif #include -#include "scsiport_int.h" - ULONG InternalDebugLevel = 0x00; #undef ScsiPortMoveMemory diff --git a/drivers/storage/scsiport/stubs.c b/drivers/storage/scsiport/stubs.c index 9c7aa0e0b6e..ac84daeb902 100644 --- a/drivers/storage/scsiport/stubs.c +++ b/drivers/storage/scsiport/stubs.c @@ -8,8 +8,7 @@ /* INCLUDES *****************************************************************/ -#include -#include +#include "precomp.h" #define NDEBUG #include diff --git a/drivers/video/displays/framebuf/CMakeLists.txt b/drivers/video/displays/framebuf/CMakeLists.txt index 2e7a143f0f7..dd9db6f11b9 100644 --- a/drivers/video/displays/framebuf/CMakeLists.txt +++ b/drivers/video/displays/framebuf/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(framebuf SHARED framebuf.rc ${CMAKE_CURRENT_BINARY_DIR}/framebuf.def) +add_pch(framebuf framebuf.h) set_entrypoint(framebuf DrvEnableDriver@12) set_subsystem(framebuf native) set_image_base(framebuf 0x00010000) diff --git a/drivers/video/displays/framebuf/framebuf.h b/drivers/video/displays/framebuf/framebuf.h index 7f222c8ce84..dec91fac2d4 100644 --- a/drivers/video/displays/framebuf/framebuf.h +++ b/drivers/video/displays/framebuf/framebuf.h @@ -18,8 +18,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#pragma once - #include #include #include diff --git a/drivers/video/displays/framebuf_new/driver.h b/drivers/video/displays/framebuf_new/driver.h index e9e617190c0..64ebbbc51a4 100644 --- a/drivers/video/displays/framebuf_new/driver.h +++ b/drivers/video/displays/framebuf_new/driver.h @@ -10,6 +10,7 @@ //#define DBG 1 #include "stddef.h" #include +#include #include "windef.h" #include "wingdi.h" #include "winddi.h" diff --git a/drivers/video/displays/vga/CMakeLists.txt b/drivers/video/displays/vga/CMakeLists.txt index fa24aed85b1..ddbb639f701 100644 --- a/drivers/video/displays/vga/CMakeLists.txt +++ b/drivers/video/displays/vga/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(vgaddi SHARED set_entrypoint(vgaddi DrvEnableDriver@12) set_subsystem(vgaddi native) set_image_base(vgaddi 0x00010000) - +add_pch(vgaddi vgaddi.h) add_importlibs(vgaddi win32k) target_link_libraries(vgaddi libcntpr) add_dependencies(vgaddi psdk bugcodes) diff --git a/drivers/video/displays/vga/vgaddi.h b/drivers/video/displays/vga/vgaddi.h index 980965da696..8988746c1ad 100644 --- a/drivers/video/displays/vga/vgaddi.h +++ b/drivers/video/displays/vga/vgaddi.h @@ -1,5 +1,3 @@ -#pragma once - #define _WINBASE_ #define _WINDOWS_H #include diff --git a/drivers/video/font/bmfd/CMakeLists.txt b/drivers/video/font/bmfd/CMakeLists.txt index 9645669efeb..5380e79adf5 100644 --- a/drivers/video/font/bmfd/CMakeLists.txt +++ b/drivers/video/font/bmfd/CMakeLists.txt @@ -4,11 +4,10 @@ add_library(bmfd SHARED font.c glyph.c) +add_pch(bmfd bmfd.h) set_entrypoint(bmfd BmfdEnableDriver@12) set_subsystem(bmfd native) set_image_base(bmfd 0x00010000) - target_link_libraries(bmfd libcntpr) - add_importlibs(bmfd win32k) add_dependencies(bmfd psdk bugcodes) diff --git a/drivers/video/font/ftfd/CMakeLists.txt b/drivers/video/font/ftfd/CMakeLists.txt index 72458f71082..c2e66436c6c 100644 --- a/drivers/video/font/ftfd/CMakeLists.txt +++ b/drivers/video/font/ftfd/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries(ftfd freetype libcntpr) +add_pch(ftfd ftfd.h) add_importlibs(ftfd win32k) add_dependencies(ftfd psdk) add_cd_file(TARGET ftfd DESTINATION reactos/system32 FOR all) diff --git a/drivers/video/font/ftfd/ftfd.h b/drivers/video/font/ftfd/ftfd.h index 61efcd86c1a..7fdeb6373b1 100644 --- a/drivers/video/font/ftfd/ftfd.h +++ b/drivers/video/font/ftfd/ftfd.h @@ -50,7 +50,7 @@ typedef struct /** Function prototypes *******************************************************/ ULONG -DbgPrint(IN PCHAR Format, IN ...); +DbgPrint(IN PCCH Format, IN ...); DHPDEV APIENTRY diff --git a/drivers/video/font/ftfd/rosglue.c b/drivers/video/font/ftfd/rosglue.c index 484fa6f3963..6a8c025a230 100644 --- a/drivers/video/font/ftfd/rosglue.c +++ b/drivers/video/font/ftfd/rosglue.c @@ -8,11 +8,7 @@ * NOTES: */ -#include -#include -#include -#include -#include +#include "ftfd.h" #define NDEBUG #include diff --git a/drivers/video/font/ftfd/sprintf.c b/drivers/video/font/ftfd/sprintf.c index 60bac91e684..39b8153a0bb 100644 --- a/drivers/video/font/ftfd/sprintf.c +++ b/drivers/video/font/ftfd/sprintf.c @@ -17,11 +17,7 @@ * Wirzenius wrote this portably, Torvalds fucked it up :-) */ -#define WIN32_NO_STATUS -#include #include -#include -#include #define ZEROPAD 1 /* pad with zero */ #define SIGN 2 /* unsigned/signed long */ diff --git a/drivers/video/miniport/vbe/CMakeLists.txt b/drivers/video/miniport/vbe/CMakeLists.txt index 590db9a20d6..7f0b42724b0 100644 --- a/drivers/video/miniport/vbe/CMakeLists.txt +++ b/drivers/video/miniport/vbe/CMakeLists.txt @@ -6,7 +6,6 @@ add_library(vbemp SHARED set_module_type(vbemp kernelmodedriver) add_importlibs(vbemp videoprt) - +add_pch(vbemp vbemp.h) target_link_libraries(vbemp libcntpr) - add_cd_file(TARGET vbemp DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/video/miniport/vbe/vbemp.h b/drivers/video/miniport/vbe/vbemp.h index 34807b2f978..1e9e3a3ee29 100644 --- a/drivers/video/miniport/vbe/vbemp.h +++ b/drivers/video/miniport/vbe/vbemp.h @@ -18,8 +18,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#pragma once - /* INCLUDES *******************************************************************/ #include "ntdef.h" diff --git a/drivers/video/videoprt/agp.c b/drivers/video/videoprt/agp.c index 188ce2efe2a..54bef7da872 100644 --- a/drivers/video/videoprt/agp.c +++ b/drivers/video/videoprt/agp.c @@ -20,8 +20,6 @@ */ #include "videoprt.h" -#include -#include /* PRIVATE FUNCTIONS **********************************************************/ diff --git a/drivers/video/videoprt/stubs.c b/drivers/video/videoprt/stubs.c index 5e557f09cfc..4745869b42f 100644 --- a/drivers/video/videoprt/stubs.c +++ b/drivers/video/videoprt/stubs.c @@ -21,7 +21,6 @@ #include "videoprt.h" -#include VP_STATUS NTAPI diff --git a/drivers/video/videoprt/videoprt.c b/drivers/video/videoprt/videoprt.c index 2fe1870ad53..f90801d986a 100644 --- a/drivers/video/videoprt/videoprt.c +++ b/drivers/video/videoprt/videoprt.c @@ -21,7 +21,6 @@ #include "videoprt.h" -#include /* GLOBAL VARIABLES ***********************************************************/ diff --git a/drivers/video/videoprt/videoprt.h b/drivers/video/videoprt/videoprt.h index 704c7d77b6a..1bf794ee9d2 100644 --- a/drivers/video/videoprt/videoprt.h +++ b/drivers/video/videoprt/videoprt.h @@ -34,6 +34,9 @@ #include #include +#include +#include + #include #define TAG_VIDEO_PORT 'PDIV' diff --git a/drivers/wdm/audio/backpln/portcls/CMakeLists.txt b/drivers/wdm/audio/backpln/portcls/CMakeLists.txt index ce2bc4d3dd3..0b5df286848 100644 --- a/drivers/wdm/audio/backpln/portcls/CMakeLists.txt +++ b/drivers/wdm/audio/backpln/portcls/CMakeLists.txt @@ -63,11 +63,10 @@ else() set_target_properties(portcls PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti") endif(MSVC) +add_pch(portcls private.hpp) set_entrypoint(portcls 0) set_image_base(portcls 0x00010000) set_subsystem(portcls native) set_target_properties(portcls PROPERTIES SUFFIX ".sys") - add_importlibs(portcls ntoskrnl ks drmk hal) - add_cd_file(TARGET portcls DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file diff --git a/drivers/wdm/audio/filters/kmixer/CMakeLists.txt b/drivers/wdm/audio/filters/kmixer/CMakeLists.txt index 36da734090c..f49556df0cd 100644 --- a/drivers/wdm/audio/filters/kmixer/CMakeLists.txt +++ b/drivers/wdm/audio/filters/kmixer/CMakeLists.txt @@ -12,6 +12,6 @@ target_link_libraries(kmixer libcntpr libsamplerate) +add_pch(kmixer kmixer.h) add_importlibs(kmixer ntoskrnl ks hal) - -add_cd_file(TARGET kmixer DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file +add_cd_file(TARGET kmixer DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/wdm/audio/filters/kmixer/kmixer.h b/drivers/wdm/audio/filters/kmixer/kmixer.h index 18c82c191a4..0564aa65ae5 100644 --- a/drivers/wdm/audio/filters/kmixer/kmixer.h +++ b/drivers/wdm/audio/filters/kmixer/kmixer.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt b/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt index ca4a76661a6..da13de3726f 100644 --- a/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt +++ b/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt @@ -20,7 +20,6 @@ target_link_libraries(wdmaud libcntpr ${PSEH_LIB}) +add_pch(wdmaud wdmaud.h) add_importlibs(wdmaud ntoskrnl ks hal) - - add_cd_file(TARGET wdmaud DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file diff --git a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index c322c3fc8a9..d1d2bccd359 100644 --- a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/drivers/wdm/audio/sysaudio/CMakeLists.txt b/drivers/wdm/audio/sysaudio/CMakeLists.txt index 078f19d1c63..94d57b651df 100644 --- a/drivers/wdm/audio/sysaudio/CMakeLists.txt +++ b/drivers/wdm/audio/sysaudio/CMakeLists.txt @@ -9,10 +9,8 @@ add_library(sysaudio SHARED pin.c sysaudio.rc) +add_pch(sysaudio sysaudio.h) set_module_type(sysaudio kernelmodedriver) - target_link_libraries(sysaudio libcntpr) - add_importlibs(sysaudio ntoskrnl ks hal) - -add_cd_file(TARGET sysaudio DESTINATION reactos/system32/drivers FOR all) \ No newline at end of file +add_cd_file(TARGET sysaudio DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/wdm/audio/sysaudio/sysaudio.h b/drivers/wdm/audio/sysaudio/sysaudio.h index bd8aea38d83..c65bf551b17 100644 --- a/drivers/wdm/audio/sysaudio/sysaudio.h +++ b/drivers/wdm/audio/sysaudio/sysaudio.h @@ -1,5 +1,3 @@ -#pragma once - #include #include #include diff --git a/include/asm/asm.inc b/include/asm/asm.inc index 6f0b0925177..db0acdb525e 100644 --- a/include/asm/asm.inc +++ b/include/asm/asm.inc @@ -32,17 +32,22 @@ rip = 0 /* To avoid reverse syntax we provide a new macro .PROC, replacing PROC... */ .PROC MACRO name - name PROC FRAME - _name: + _&name PROC ENDM #define FUNC .PROC /* ... and .ENDP, replacing ENDP */ .ENDP MACRO name - name ENDP + _&name ENDP ENDM #define ENDFUNC .ENDP +/* check http://msdn.microsoft.com/en-us/library/9c9k076y%28VS.80%29.aspx + and http://msdn.microsoft.com/en-us/library/ms679352%28VS.85%29.aspx */ +FPO MACRO cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame + .FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame) +ENDM + /* MASM doesn't have an ASCII macro */ .ASCII MACRO text:VARARG DB text @@ -184,7 +189,7 @@ ENDM /* To avoid reverse syntax we provide a new macro .PROC, replacing PROC... */ .macro .PROC name .func \name - \name: + _\name: .cfi_startproc .equ cfa_current_offset, -8 .endm @@ -237,6 +242,12 @@ ENDM .text .endm +/* check http://msdn.microsoft.com/en-us/library/9c9k076y%28VS.80%29.aspx + and http://msdn.microsoft.com/en-us/library/ms679352%28VS.85%29.aspx */ +.macro FPO cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame + /* dummy */ +.endm + /* Macros for x64 stack unwind OPs */ .macro .allocstack size @@ -316,3 +327,10 @@ ENDM #define NUL "\0" #endif + +/* Common definitions for FPO macro + see http://msdn.microsoft.com/en-us/library/ms679352%28VS.85%29.aspx */ +#define FRAME_FPO 0 +#define FRAME_TRAP 1 +#define FRAME_TSS 2 +#define FRAME_NONFPO 3 diff --git a/include/asm/syscalls.inc b/include/asm/syscalls.inc index 96784e5a2e4..83b86e37d70 100644 --- a/include/asm/syscalls.inc +++ b/include/asm/syscalls.inc @@ -71,24 +71,42 @@ MACRO(MAKE_LABEL, Name, Stackbytes) PUBLIC _&Name&@&Stackbytes _&Name&@&Stackbytes: ENDM +MACRO(START_PROC, Name, Stackbytes) + PUBLIC _&Name&@&Stackbytes + .PROC &Name&@&Stackbytes + FPO 0, 0, 0, 0, 0, FRAME_FPO +ENDM +MACRO(END_PROC, Name, Stackbytes) + .ENDP &Name&@&Stackbytes +ENDM #else MACRO(MAKE_LABEL, Name, Stackbytes) PUBLIC &Name &Name: ENDM +MACRO(START_PROC, Name, Stackbytes) + PUBLIC &Name + .PROC &Name + FPO 0, 0, 0, 0, 0, FRAME_FPO +ENDM +MACRO(END_PROC, Name, Stackbytes) + .ENDP &Name +ENDM #endif MACRO(STUB_U, Name, ArgCount) Stackbytes = 4 * &ArgCount MAKE_LABEL Zw&Name, %Stackbytes - MAKE_LABEL Nt&Name, %Stackbytes + START_PROC Nt&Name, %Stackbytes STUBCODE_U SyscallId, %Stackbytes + END_PROC Nt&Name, %Stackbytes SyscallId = SyscallId + 1 ENDM MACRO(STUB_K, Name, ArgCount) Stackbytes = 4 * &ArgCount - MAKE_LABEL Zw&Name, %Stackbytes + START_PROC Zw&Name, %Stackbytes STUBCODE_K SyscallId, %Stackbytes + END_PROC Zw&Name, %Stackbytes SyscallId = SyscallId + 1 ENDM diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index be27ea014af..862ac89d73b 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -5600,8 +5600,8 @@ NTSTATUS NTAPI ZwDisplayString( IN PUNICODE_STRING String); - -NTSYSAPI + +NTSYSCALLAPI NTSTATUS NTAPI ZwPowerInformation( diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h index 8c4f1a1bbad..3bf4a1c25c5 100644 --- a/include/ddk/ntifs.h +++ b/include/ddk/ntifs.h @@ -9615,7 +9615,7 @@ ZwFlushBuffersFile( #if (VER_PRODUCTBUILD >= 2195) -NTSYSAPI +NTSYSCALLAPI NTSTATUS NTAPI ZwInitiatePowerAction ( diff --git a/include/ddk/ntimage.h b/include/ddk/ntimage.h index 2dac14a3053..b512a71d7cf 100644 --- a/include/ddk/ntimage.h +++ b/include/ddk/ntimage.h @@ -419,6 +419,12 @@ typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; #define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 #define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 +// +// Loader Flags +// +#define IMAGE_LOADER_FLAGS_COMPLUS 0x00000001 +#define IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL 0x01000000 + // // Directory Entry Specifiers // diff --git a/include/ndk/exfuncs.h b/include/ndk/exfuncs.h index 0d40a3fd0d4..bca62309f97 100644 --- a/include/ndk/exfuncs.h +++ b/include/ndk/exfuncs.h @@ -114,30 +114,17 @@ ExEnumHandleTable( ); // -// Resource Functions +// HardError Functions // -PVOID -NTAPI -ExEnterCriticalRegionAndAcquireResourceExclusive( - IN PERESOURCE Resource -); - -PVOID -NTAPI -ExEnterCriticalRegionAndAcquireResourceShared( - IN PERESOURCE Resource -); - -PVOID +NTSTATUS NTAPI -ExEnterCriticalRegionAndAcquireSharedWaitForExclusive( - IN PERESOURCE Resource -); - -VOID -FASTCALL -ExReleaseResourceAndLeaveCriticalRegion( - IN PERESOURCE Resource +ExRaiseHardError( + IN NTSTATUS ErrorStatus, + IN ULONG NumberOfParameters, + IN ULONG UnicodeStringParameterMask, + IN PULONG_PTR Parameters, + IN ULONG ValidResponseOptions, + OUT PULONG Response ); #endif diff --git a/include/ndk/extypes.h b/include/ndk/extypes.h index 79669029b68..19dd221a074 100644 --- a/include/ndk/extypes.h +++ b/include/ndk/extypes.h @@ -175,7 +175,9 @@ typedef enum _HARDERROR_RESPONSE_OPTION OptionRetryCancel, OptionYesNo, OptionYesNoCancel, - OptionShutdownSystem + OptionShutdownSystem, + OptionOkNoWait, + OptionCancelTryContinue } HARDERROR_RESPONSE_OPTION, *PHARDERROR_RESPONSE_OPTION; typedef enum _HARDERROR_RESPONSE diff --git a/include/ndk/kefuncs.h b/include/ndk/kefuncs.h index 78f6b16dec9..4888006a86e 100644 --- a/include/ndk/kefuncs.h +++ b/include/ndk/kefuncs.h @@ -126,6 +126,13 @@ KeAcquireQueuedSpinLockRaiseToSynch( IN KSPIN_LOCK_QUEUE_NUMBER LockNumber ); +BOOLEAN +FASTCALL +KeTryToAcquireQueuedSpinLockRaiseToSynch( + IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, + IN PKIRQL OldIrql +); + VOID FASTCALL KeAcquireInStackQueuedSpinLockRaiseToSynch( diff --git a/include/ndk/ldrtypes.h b/include/ndk/ldrtypes.h index 8887a040b07..84ff1370352 100644 --- a/include/ndk/ldrtypes.h +++ b/include/ndk/ldrtypes.h @@ -61,18 +61,30 @@ Author: // // Dll Characteristics for LdrLoadDll // -#define LDR_IGNORE_CODE_AUTHZ_LEVEL 0x00001000 +#define LDR_IGNORE_CODE_AUTHZ_LEVEL 0x00001000 // // LdrAddRef Flags // -#define LDR_PIN_MODULE 0x00000001 +#define LDR_ADDREF_DLL_PIN 0x00000001 // // LdrLockLoaderLock Flags // -#define LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 -#define LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY 0x00000002 +#define LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 +#define LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY 0x00000002 + +// +// LdrUnlockLoaderLock Flags +// +#define LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001 + +// +// LdrGetDllHandleEx Flags +// +#define LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT 0x00000001 +#define LDR_GET_DLL_HANDLE_EX_PIN 0x00000002 + #define LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID 0 #define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED 1 @@ -205,4 +217,14 @@ typedef struct _ALT_RESOURCE_MODULE typedef VOID (NTAPI LDR_ENUM_CALLBACK)(IN PLDR_DATA_TABLE_ENTRY ModuleInformation, IN PVOID Parameter, OUT BOOLEAN *Stop); typedef LDR_ENUM_CALLBACK *PLDR_ENUM_CALLBACK; +// +// DLL Main Routine +// +typedef BOOLEAN +(NTAPI *PDLL_INIT_ROUTINE)( + IN PVOID DllHandle, + IN ULONG Reason, + IN PCONTEXT Context OPTIONAL +); + #endif diff --git a/include/ndk/lpctypes.h b/include/ndk/lpctypes.h index 44419618d5d..2f869a8d9e9 100644 --- a/include/ndk/lpctypes.h +++ b/include/ndk/lpctypes.h @@ -209,8 +209,11 @@ typedef struct _LPCP_PORT_OBJECT SECURITY_CLIENT_CONTEXT StaticSecurity; LIST_ENTRY LpcReplyChainHead; LIST_ENTRY LpcDataInfoChainHead; - PEPROCESS ServerProcess; - PEPROCESS MappingProcess; + union + { + PEPROCESS ServerProcess; + PEPROCESS MappingProcess; + }; ULONG MaxMessageLength; ULONG MaxConnectionInfoLength; ULONG Flags; diff --git a/include/ndk/pofuncs.h b/include/ndk/pofuncs.h index 44bf815896f..a1e677f3b4d 100644 --- a/include/ndk/pofuncs.h +++ b/include/ndk/pofuncs.h @@ -18,6 +18,7 @@ Author: #ifndef _POFUNCS_H #define _POFUNCS_H +#ifndef _PO_DDK_ // // Dependencies @@ -57,28 +58,80 @@ NtSetSystemPowerState( IN ULONG Flags ); -NTSYSAPI +NTSYSCALLAPI +NTSTATUS +NTAPI +NtGetDevicePowerState( + IN HANDLE Device, + IN PDEVICE_POWER_STATE PowerState +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtRequestWakeupLatency( + IN LATENCY_TIME latency +); + +NTSYSCALLAPI +BOOLEAN +NTAPI +NtIsSystemResumeAutomatic(VOID); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtSetThreadExecutionState( + IN EXECUTION_STATE esFlags, + OUT EXECUTION_STATE *PreviousFlags +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtInitiatePowerAction( + IN POWER_ACTION SystemAction, + IN SYSTEM_POWER_STATE MinSystemState, + IN ULONG Flags, + IN BOOLEAN Asynchronous +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtRequestDeviceWakeup( + IN HANDLE Device +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCancelDeviceWakeupRequest( + IN HANDLE Device +); +#endif +NTSYSCALLAPI NTSTATUS NTAPI ZwInitiatePowerAction( - POWER_ACTION SystemAction, - SYSTEM_POWER_STATE MinSystemState, - ULONG Flags, - BOOLEAN Asynchronous + IN POWER_ACTION SystemAction, + IN SYSTEM_POWER_STATE MinSystemState, + IN ULONG Flags, + IN BOOLEAN Asynchronous ); -NTSYSAPI +NTSYSCALLAPI NTSTATUS NTAPI ZwPowerInformation( - POWER_INFORMATION_LEVEL PowerInformationLevel, - PVOID InputBuffer, - ULONG InputBufferLength, - PVOID OutputBuffer, - ULONG OutputBufferLength + IN POWER_INFORMATION_LEVEL PowerInformationLevel, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength ); -NTSYSAPI +NTSYSCALLAPI NTSTATUS NTAPI ZwSetSystemPowerState( diff --git a/include/ndk/pstypes.h b/include/ndk/pstypes.h index 414e2dcbec1..d0f2fecc982 100644 --- a/include/ndk/pstypes.h +++ b/include/ndk/pstypes.h @@ -117,7 +117,6 @@ Author: #define PSP_LONG_QUANTUMS 16 #ifndef NTOS_MODE_USER - // // Thread Access Types // @@ -149,6 +148,7 @@ Author: #define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | \ SYNCHRONIZE | \ 0xFFF) +#endif // // Thread Base Priorities @@ -162,7 +162,6 @@ Author: // TLS Slots // #define TLS_MINIMUM_AVAILABLE 64 -#endif // // Job Access Types @@ -194,7 +193,6 @@ Author: #define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK 0x1000 #define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x2000 - // // Cross Thread Flags // @@ -223,9 +221,7 @@ Author: #define STA_LPC_EXIT_THREAD_CALLED_BIT 0x2 #define STA_ADDRESS_SPACE_OWNER_BIT 0x4 #define STA_OWNS_WORKING_SET_BITS 0x1F8 -#endif -#define TLS_EXPANSION_SLOTS 1024 // // Process Flags // @@ -261,8 +257,22 @@ Author: // Vista Process Flags // #define PSF2_PROTECTED_BIT 0x800 +#endif + +// +// TLS/FLS Defines +// +#define TLS_EXPANSION_SLOTS 1024 #ifdef NTOS_MODE_USER +// +// Thread Native Base Priorities +// +#define LOW_PRIORITY 0 +#define LOW_REALTIME_PRIORITY 16 +#define HIGH_PRIORITY 31 +#define MAXIMUM_PRIORITY 32 + // // Current Process/Thread built-in 'special' handles // diff --git a/include/ndk/rtlfuncs.h b/include/ndk/rtlfuncs.h index 6807128b626..f70ceab3a70 100644 --- a/include/ndk/rtlfuncs.h +++ b/include/ndk/rtlfuncs.h @@ -171,6 +171,17 @@ RtlInitEmptyUnicodeString(OUT PUNICODE_STRING UnicodeString, UnicodeString->MaximumLength = BufferSize; UnicodeString->Buffer = Buffer; } + +FORCEINLINE +VOID +RtlInitEmptyAnsiString(OUT PANSI_STRING AnsiString, + IN PSTR Buffer, + IN USHORT BufferSize) +{ + AnsiString->Length = 0; + AnsiString->MaximumLength = BufferSize; + AnsiString->Buffer = Buffer; +} // // LUID Macros @@ -2323,7 +2334,7 @@ RtlDetermineDosPathNameType_U( ); NTSYSAPI -ULONG +RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_Ustr( IN PCUNICODE_STRING Path @@ -2348,7 +2359,7 @@ RtlDosPathNameToNtPathName_U( IN PCWSTR DosPathName, OUT PUNICODE_STRING NtPathName, OUT PCWSTR *NtFileNamePart, - OUT CURDIR *DirectoryInfo + OUT PRTL_RELATIVE_NAME_U DirectoryInfo ); NTSYSAPI @@ -2379,18 +2390,6 @@ RtlGetFullPathName_U( OUT PWSTR *ShortName ); -NTSYSAPI -ULONG -NTAPI -RtlGetFullPathName_Ustr( - IN PUNICODE_STRING FileName, - IN ULONG Size, - IN PWSTR Buffer, - OUT PWSTR *ShortName, - OUT PBOOLEAN InvalidName, - OUT RTL_PATH_TYPE *PathType -); - NTSYSAPI ULONG NTAPI @@ -2424,6 +2423,12 @@ RtlQueryEnvironmentVariable_U( PUNICODE_STRING Value ); +VOID +NTAPI +RtlReleaseRelativeName( + IN PRTL_RELATIVE_NAME_U RelativeName +); + NTSYSAPI NTSTATUS NTAPI @@ -3052,12 +3057,21 @@ LdrRelocateImageWithBias( // Activation Context Functions // #ifdef NTOS_MODE_USER +NTSYSAPI +NTSTATUS +NTAPI +RtlActivateActivationContextEx( + IN ULONG Flags, + IN PTEB Teb, + IN PVOID Context, + IN PULONG_PTR Cookie +); NTSYSAPI NTSTATUS NTAPI RtlActivateActivationContext( - IN ULONG Unknown, + IN ULONG Flags, IN HANDLE Handle, OUT PULONG_PTR Cookie ); @@ -3069,7 +3083,6 @@ RtlAddRefActivationContext( PVOID Context ); - NTSYSAPI PRTL_ACTIVATION_CONTEXT_STACK_FRAME FASTCALL diff --git a/include/ndk/rtltypes.h b/include/ndk/rtltypes.h index 3b932372ca9..508737967a7 100644 --- a/include/ndk/rtltypes.h +++ b/include/ndk/rtltypes.h @@ -244,6 +244,11 @@ C_ASSERT(HEAP_CREATE_VALID_MASK == 0x0007F0FF); // #define RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE 4 +// +// RtlImageNtHeaderEx Flags +// +#define RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK 0x00000001 + // // Codepages // @@ -251,6 +256,11 @@ C_ASSERT(HEAP_CREATE_VALID_MASK == 0x0007F0FF); #define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag #define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo +// +// Activation Contexts +// +#define INVALID_ACTIVATION_CONTEXT (PVOID)0xFFFFFFFF + // // C++ CONST casting // @@ -753,20 +763,28 @@ typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *Previous; PACTIVATION_CONTEXT ActivationContext; ULONG Flags; -} RTL_ACTIVATION_CONTEXT_STACK_FRAME, - *PRTL_ACTIVATION_CONTEXT_STACK_FRAME; +} RTL_ACTIVATION_CONTEXT_STACK_FRAME, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME; + +typedef struct _RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC +{ + SIZE_T Size; + ULONG Format; + RTL_ACTIVATION_CONTEXT_STACK_FRAME Frame; +} RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC, *PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC; typedef struct _RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED { - ULONG Size; + SIZE_T Size; ULONG Format; RTL_ACTIVATION_CONTEXT_STACK_FRAME Frame; PVOID Extra1; PVOID Extra2; PVOID Extra3; PVOID Extra4; -} RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED, - *PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED; +} RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED, *PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED; + +typedef RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME; +typedef PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME; #if (NTDDI_VERSION >= NTDDI_WS03) typedef struct _ACTIVATION_CONTEXT_STACK @@ -776,8 +794,7 @@ typedef struct _ACTIVATION_CONTEXT_STACK ULONG Flags; ULONG NextCookieSequenceNumber; ULONG StackId; -} ACTIVATION_CONTEXT_STACK, - *PACTIVATION_CONTEXT_STACK; +} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK; #else typedef struct _ACTIVATION_CONTEXT_STACK { @@ -1012,6 +1029,14 @@ typedef struct _CURDIR HANDLE Handle; } CURDIR, *PCURDIR; +typedef struct _RTLP_CURDIR_REF *PRTLP_CURDIR_REF; +typedef struct _RTL_RELATIVE_NAME_U +{ + UNICODE_STRING RelativeName; + HANDLE ContainingDirectory; + PRTLP_CURDIR_REF CurDirRef; +} RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U; + typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; diff --git a/include/psdk/ntdef.h b/include/psdk/ntdef.h index 634294a33d4..8b578a9a827 100644 --- a/include/psdk/ntdef.h +++ b/include/psdk/ntdef.h @@ -460,6 +460,8 @@ typedef struct _UNICODE_STRING { } UNICODE_STRING, *PUNICODE_STRING; typedef const UNICODE_STRING* PCUNICODE_STRING; #define UNICODE_NULL ((WCHAR)0) +#define UNICODE_STRING_MAX_BYTES ((USHORT) 65534) +#define UNICODE_STRING_MAX_CHARS (32767) typedef struct _CSTRING { USHORT Length; diff --git a/include/psdk/propkeydef.h b/include/psdk/propkeydef.h index 2a796eaf3c4..85b29647caa 100644 --- a/include/psdk/propkeydef.h +++ b/include/psdk/propkeydef.h @@ -58,6 +58,8 @@ #ifndef _PROPERTYKEY_EQUALITY_OPERATORS_ #define _PROPERTYKEY_EQUALITY_OPERATORS_ #ifdef __cplusplus +extern "C++" +{ inline bool operator==(REFPROPERTYKEY guidOne, REFPROPERTYKEY guidOther) { return IsEqualPropertyKey(guidOne, guidOther); @@ -66,5 +68,6 @@ inline bool operator!=(REFPROPERTYKEY guidOne, REFPROPERTYKEY guidOther) { return !(guidOne == guidOther); } +} //extern "C++" #endif #endif diff --git a/include/psdk/winbase.h b/include/psdk/winbase.h index 9049f50d2a2..12509445483 100644 --- a/include/psdk/winbase.h +++ b/include/psdk/winbase.h @@ -222,6 +222,7 @@ extern "C" { #define SETRTS 3 #define SETXOFF 1 #define SETXON 2 +#define RESETDEV 7 #define SETBREAK 8 #define CLRBREAK 9 #define STILL_ACTIVE 0x103 diff --git a/include/psdk/winnt.h b/include/psdk/winnt.h index 8dfdfbfabb4..25ff67708ec 100644 --- a/include/psdk/winnt.h +++ b/include/psdk/winnt.h @@ -284,6 +284,8 @@ typedef LONGLONG USN; #endif #define ANSI_NULL ((CHAR)0) #define UNICODE_NULL ((WCHAR)0) +#define UNICODE_STRING_MAX_BYTES ((USHORT) 65534) +#define UNICODE_STRING_MAX_CHARS (32767) typedef BYTE BOOLEAN,*PBOOLEAN; #endif typedef BYTE FCHAR; @@ -311,6 +313,22 @@ typedef DWORD FLONG; #define ERROR_SEVERITY_INFORMATIONAL 0x40000000 #define ERROR_SEVERITY_WARNING 0x80000000 #define ERROR_SEVERITY_ERROR 0xC0000000 + +#ifdef __cplusplus +#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \ +extern "C++" { \ + inline ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a)|((int)b)); } \ + inline ENUMTYPE operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) |= ((int)b)); } \ + inline ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a)&((int)b)); } \ + inline ENUMTYPE operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) &= ((int)b)); } \ + inline ENUMTYPE operator ~ (ENUMTYPE a) { return (ENUMTYPE)(~((int)a)); } \ + inline ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a)^((int)b)); } \ + inline ENUMTYPE operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) ^= ((int)b)); } \ +} +#else +#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) /* */ +#endif + /* also in ddk/ntifs.h */ #define COMPRESSION_FORMAT_NONE (0x0000) #define COMPRESSION_FORMAT_DEFAULT (0x0001) @@ -3300,6 +3318,21 @@ typedef struct _QUOTA_LIMITS { SIZE_T PagefileLimit; LARGE_INTEGER TimeLimit; } QUOTA_LIMITS,*PQUOTA_LIMITS; + +typedef struct _QUOTA_LIMITS_EX { + SIZE_T PagedPoolLimit; + SIZE_T NonPagedPoolLimit; + SIZE_T MinimumWorkingSetSize; + SIZE_T MaximumWorkingSetSize; + SIZE_T PagefileLimit; + LARGE_INTEGER TimeLimit; + SIZE_T Reserved1; + SIZE_T Reserved2; + SIZE_T Reserved3; + SIZE_T Reserved4; + ULONG Flags; + ULONG Reserved5; +} QUOTA_LIMITS_EX, *PQUOTA_LIMITS_EX; typedef struct _IO_COUNTERS { ULONGLONG ReadOperationCount; diff --git a/include/reactos/asm.inc b/include/reactos/asm.inc index 45c9068abf4..a99ecfb7074 100644 --- a/include/reactos/asm.inc +++ b/include/reactos/asm.inc @@ -41,6 +41,12 @@ ENDM name ENDP ENDM +/* check http://msdn.microsoft.com/en-us/library/9c9k076y%28VS.80%29.aspx + and http://msdn.microsoft.com/en-us/library/ms679352%28VS.85%29.aspx */ +FPO MACRO cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame + .FPO (cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame) +ENDM + /* MASM doesn't have an ASCII macro */ .ASCII MACRO text DB text @@ -143,7 +149,7 @@ ENDM /* To avoid reverse syntax we provide a new macro .PROC, replacing PROC... */ .macro .PROC name .func \name - \name: + _\name: .cfi_startproc .equ cfa_current_offset, -8 .endm @@ -192,6 +198,12 @@ ENDM .text .endm +/* check http://msdn.microsoft.com/en-us/library/9c9k076y%28VS.80%29.aspx + and http://msdn.microsoft.com/en-us/library/ms679352%28VS.85%29.aspx */ +.macro FPO cdwLocals, cdwParams, cbProlog, cbRegs, fUseBP, cbFrame + /* dummy */ +.endm + /* Macros for x64 stack unwind OPs */ .macro .allocstack size @@ -259,4 +271,11 @@ code = 1 #endif +/* Common definitions for FPO macro + see http://msdn.microsoft.com/en-us/library/ms679352%28VS.85%29.aspx */ +#define FRAME_FPO 0 +#define FRAME_TRAP 1 +#define FRAME_TSS 2 +#define FRAME_NONFPO 3 + #endif /* _ASM_INC_ */ diff --git a/include/reactos/idl/eventlogrpc.idl b/include/reactos/idl/eventlogrpc.idl index e5cdbd3459d..5059e62ea7d 100644 --- a/include/reactos/idl/eventlogrpc.idl +++ b/include/reactos/idl/eventlogrpc.idl @@ -190,24 +190,15 @@ interface eventlog /* Function 19 */ NTSTATUS ElfrRegisterClusterSvc( -#ifndef __midl - [in] handle_t BindingHandle -#endif - ); /* FIXME */ + [in] handle_t BindingHandle); /* Function 20 */ NTSTATUS ElfrDeregisterClusterSvc( -#ifndef __midl - [in] handle_t BindingHandle -#endif - ); /* FIXME */ + [in] handle_t BindingHandle); /* Function 21 */ NTSTATUS ElfrWriteClusterEvents( -#ifndef __midl - [in] handle_t BindingHandle -#endif - ); /* FIXME */ + [in] handle_t BindingHandle); /* Function 22 */ NTSTATUS ElfrGetLogInformation( diff --git a/include/reactos/mc/ntstatus.mc b/include/reactos/mc/ntstatus.mc index 9fe190409ea..4b26f193780 100644 --- a/include/reactos/mc/ntstatus.mc +++ b/include/reactos/mc/ntstatus.mc @@ -411,6 +411,26 @@ Language=English One of the files containing the system's Registry data had to be recovered by use of a log or alternate copy. The recovery was successful. +. +MessageId=0xa +Severity=Informational +Facility=System +SymbolicName=STATUS_FT_READ_RECOVERY_FROM_BACKUP +Language=English +{Redundant Read} +To satisfy a read request, the Windows NT fault-tolerant file system successfully read the requested data from a redundant copy. +This was done because the file system encountered a failure on a member of the fault-tolerant volume but was unable to reassign the failing area of the device. + +. +MessageId=0xb +Severity=Informational +Facility=System +SymbolicName=STATUS_FT_WRITE_RECOVERY +Language=English +{Redundant Write} +To satisfy a write request, the Windows NT fault-tolerant file system successfully wrote a redundant copy of the information. +This was done because the file system encountered a failure on a member of the fault-tolerant volume but was unable to reassign the failing area of the device. + . MessageId=0xc Severity=Informational @@ -421,6 +441,33 @@ Language=English A serial I/O operation completed because the time-out period expired. (The IOCTL_SERIAL_XOFF_COUNTER had not reached zero.) +. +MessageId=0xd +Severity=Informational +Facility=System +SymbolicName=STATUS_NULL_LM_PASSWORD +Language=English +{Password Too Complex} +The Windows password is too complex to be converted to a LAN Manager password. The LAN Manager password that returned is a NULL string. + +. +MessageId=0xe +Severity=Informational +Facility=System +SymbolicName=STATUS_IMAGE_MACHINE_TYPE_MISMATCH +Language=English +{Machine Type Mismatch} +The image file %hs is valid, but is for a machine type other than the current machine. + +. +MessageId=0xf +Severity=Informational +Facility=System +SymbolicName=STATUS_RECEIVE_PARTIAL +Language=English +{Partial Data Received} +The network transport returned partial data to its client. The remaining data will be sent later. + . MessageId=0x10 Severity=Informational @@ -1715,6 +1762,24 @@ SymbolicName=STATUS_INVALID_SECURITY_DESCR Language=English Indicates the SECURITY_DESCRIPTOR structure is not valid. +. +MessageId=0x7a +Severity=Error +Facility=System +SymbolicName=STATUS_PROCEDURE_NOT_FOUND +Language=English +Indicates the specified procedure address cannot be found in the DLL. + +. +MessageId=0x7b +Severity=Error +Facility=System +SymbolicName=STATUS_INVALID_IMAGE_FORMAT +Language=English +{Bad Image} +%hs is either not designed for ReactOS or it contains an error. +Try reinstalling the application using the original installation media or contact the software vendor for support. + . MessageId=0x7c Severity=Error diff --git a/include/reactos/rossym.h b/include/reactos/rossym.h index 785299f8779..0c6c9d98f39 100644 --- a/include/reactos/rossym.h +++ b/include/reactos/rossym.h @@ -12,6 +12,10 @@ #define ROSSYM_SECTION_NAME ".rossym" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct _ROSSYM_HEADER { unsigned long SymbolsOffset; unsigned long SymbolsLength; @@ -86,6 +90,18 @@ typedef struct _ROSSYM_LINEINFO { ROSSYM_PARAMETER Parameters[16]; } ROSSYM_LINEINFO, *PROSSYM_LINEINFO; +typedef struct _ROSSYM_AGGREGATE_MEMBER { + PCHAR Name, Type; + ULONG BaseOffset, Size; + ULONG FirstBit, Bits; + ULONG TypeId; +} ROSSYM_AGGREGATE_MEMBER, *PROSSYM_AGGREGATE_MEMBER; + +typedef struct _ROSSYM_AGGREGATE { + ULONG NumElements; + PROSSYM_AGGREGATE_MEMBER Elements; +} ROSSYM_AGGREGATE, *PROSSYM_AGGREGATE; + typedef struct _ROSSYM_CALLBACKS { PVOID (*AllocMemProc)(ULONG_PTR Size); VOID (*FreeMemProc)(PVOID Area); @@ -132,6 +148,13 @@ BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, #endif VOID RosSymFreeInfo(PROSSYM_LINEINFO RosSymLineInfo); VOID RosSymDelete(PROSSYM_INFO RosSymInfo); +BOOLEAN +RosSymAggregate(PROSSYM_INFO RosSymInfo, PCHAR Type, PROSSYM_AGGREGATE Aggregate); +VOID RosSymFreeAggregate(PROSSYM_AGGREGATE Aggregate); + +#ifdef __cplusplus +} +#endif #endif /* REACTOS_ROSSYM_H_INCLUDED */ diff --git a/include/reactos/subsys/csrss/csrss.h b/include/reactos/subsys/csrss/csrss.h index 4c9f44fd43c..e8c37bbaba7 100644 --- a/include/reactos/subsys/csrss/csrss.h +++ b/include/reactos/subsys/csrss/csrss.h @@ -692,6 +692,75 @@ typedef struct _CSR_API_MESSAGE } Data; } CSR_API_MESSAGE, *PCSR_API_MESSAGE; +typedef struct _NLS_USER_INFO +{ + WCHAR iCountry[80]; + WCHAR sCountry[80]; + WCHAR sList[80]; + WCHAR iMeasure[80]; + WCHAR iPaperSize[80]; + WCHAR sDecimal[80]; + WCHAR sThousand[80]; + WCHAR sGrouping[80]; + WCHAR iDigits[80]; + WCHAR iLZero[80]; + WCHAR iNegNumber[80]; + WCHAR sNativeDigits[80]; + WCHAR iDigitSubstitution[80]; + WCHAR sCurrency[80]; + WCHAR sMonDecSep[80]; + WCHAR sMonThouSep[80]; + WCHAR sMonGrouping[80]; + WCHAR iCurrDigits[80]; + WCHAR iCurrency[80]; + WCHAR iNegCurr[80]; + WCHAR sPosSign[80]; + WCHAR sNegSign[80]; + WCHAR sTimeFormat[80]; + WCHAR s1159[80]; + WCHAR s2359[80]; + WCHAR sShortDate[80]; + WCHAR sYearMonth[80]; + WCHAR sLongDate[80]; + WCHAR iCalType[80]; + WCHAR iFirstDay[80]; + WCHAR iFirstWeek[80]; + WCHAR sLocale[80]; + WCHAR sLocaleName[85]; + LCID UserLocaleId; + LUID InteractiveUserLuid; + CHAR InteractiveUserSid[68]; // SECURITY_MAX_SID_SIZE to make ros happy + ULONG ulCacheUpdateCount; +} NLS_USER_INFO, *PNLS_USER_INFO; + + +typedef struct _BASE_STATIC_SERVER_DATA +{ + UNICODE_STRING WindowsDirectory; + UNICODE_STRING WindowsSystemDirectory; + UNICODE_STRING NamedObjectDirectory; + USHORT WindowsMajorVersion; + USHORT WindowsMinorVersion; + USHORT BuildNumber; + USHORT CSDNumber; + USHORT RCNumber; + WCHAR CSDVersion[128]; + SYSTEM_BASIC_INFORMATION SysInfo; + SYSTEM_TIMEOFDAY_INFORMATION TimeOfDay; + PVOID IniFileMapping; + NLS_USER_INFO NlsUserInfo; + BOOLEAN DefaultSeparateVDM; + BOOLEAN IsWowTaskReady; + UNICODE_STRING WindowsSys32x86Directory; + BOOLEAN fTermsrvAppInstallMode; + TIME_ZONE_INFORMATION tziTermsrvClientTimeZone; + KSYSTEM_TIME ktTermsrvClientBias; + ULONG TermsrvClientTimeZoneId; + BOOLEAN LUIDDeviceMapsEnabled; + ULONG TermsrvClientTimeZoneChangeNum; +} BASE_STATIC_SERVER_DATA, *PBASE_STATIC_SERVER_DATA; + + /* Types used in the new CSR. Temporarly here for proper compile of NTDLL */ #define CSR_SRV_SERVER 0 diff --git a/include/reactos/version.cmake b/include/reactos/version.cmake index 140ad1af0f4..57b156d7573 100644 --- a/include/reactos/version.cmake +++ b/include/reactos/version.cmake @@ -1,64 +1,65 @@ -macro(today RESULT) - if(CMAKE_HOST_WIN32) - execute_process(COMMAND "${REACTOS_SOURCE_DIR}/tools/getdate.exe" OUTPUT_VARIABLE ${RESULT}) - string(STRIP ${${RESULT}} ${RESULT}) - elseif(CMAKE_HOST_UNIX) - execute_process(COMMAND "date" "+%Y%m%d" OUTPUT_VARIABLE ${RESULT}) - string(STRIP ${${RESULT}} ${RESULT}) - else() - message(SEND_ERROR "date not implemented") - set(${RESULT} 00000000) - endif() -endmacro() - -macro(inttohex INTVALUE OUTPUT_VARIABLE) - list(APPEND HEXLIST 0 1 2 3 4 5 6 7 8 9 a b c d e f) - list(GET HEXLIST ${INTVALUE} ${OUTPUT_VARIABLE}) -endmacro() - -macro(converttohex INTVALUE OUTPUT_VARIABLE) - set(REMAINING ${INTVALUE}) - while(REMAINING) - math(EXPR REMAINDER "${REMAINING}%16") - inttohex(${REMAINDER} HEXCHAR) - math(EXPR REMAINING "${REMAINING}/16") - set(${OUTPUT_VARIABLE} "${HEXCHAR}${${OUTPUT_VARIABLE}}") - endwhile() -endmacro() - -today(KERNEL_VERSION_BUILD) - -set(KERNEL_VERSION_MAJOR "0") -set(KERNEL_VERSION_MINOR "4") -set(KERNEL_VERSION_PATCH_LEVEL "0") -set(COPYRIGHT_YEAR "2011") -# KERNEL_VERSION_BUILD_TYPE is "SVN", "RC1", "RC2" or "" (for the release) -set(KERNEL_VERSION_BUILD_TYPE "SVN") - - -set(KERNEL_VERSION "${KERNEL_VERSION_MAJOR}.${KERNEL_VERSION_MINOR}") -if(KERNEL_VERSION_PATCH_LEVEL) - set(KERNEL_VERSION "${KERNEL_VERSION}.${KERNEL_VERSION_PATCH_LEVEL}-${KERNEL_VERSION_BUILD_TYPE}") -else() - set(KERNEL_VERSION "${KERNEL_VERSION}-${KERNEL_VERSION_BUILD_TYPE}") -endif() - -math(EXPR REACTOS_DLL_VERSION_MAJOR "${KERNEL_VERSION_MAJOR}+42") -set(DLL_VERSION_STR "${REACTOS_DLL_VERSION_MAJOR}.${KERNEL_VERSION_MINOR}-${KERNEL_VERSION_BUILD_TYPE}") - -# get svn revision number -set(REVISION "-rUNKNOWN") -set(KERNEL_VERSION_BUILD_HEX "0") -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn") - find_package(Subversion) - if(Subversion_FOUND) - subversion_wc_info(${CMAKE_CURRENT_SOURCE_DIR} SVNINFO) - if(SVNINFO_WC_REVISION) - set(REVISION "-r${SVNINFO_WC_REVISION}") - converttohex(${SVNINFO_WC_REVISION} KERNEL_VERSION_BUILD_HEX) - endif() - endif() -endif() - -configure_file(include/reactos/version.h.cmake ${REACTOS_BINARY_DIR}/include/reactos/version.h) -configure_file(include/reactos/buildno.h.cmake ${REACTOS_BINARY_DIR}/include/reactos/buildno.h) +macro(today RESULT) + if(CMAKE_HOST_WIN32) + execute_process(COMMAND "${REACTOS_SOURCE_DIR}/tools/getdate.exe" OUTPUT_VARIABLE ${RESULT}) + string(STRIP ${${RESULT}} ${RESULT}) + elseif(CMAKE_HOST_UNIX) + execute_process(COMMAND "date" "+%Y%m%d" OUTPUT_VARIABLE ${RESULT}) + string(STRIP ${${RESULT}} ${RESULT}) + else() + message(SEND_ERROR "date not implemented") + set(${RESULT} 00000000) + endif() +endmacro() + +macro(inttohex INTVALUE OUTPUT_VARIABLE) + list(APPEND HEXLIST 0 1 2 3 4 5 6 7 8 9 a b c d e f) + list(GET HEXLIST ${INTVALUE} ${OUTPUT_VARIABLE}) +endmacro() + +macro(converttohex INTVALUE OUTPUT_VARIABLE) + set(${OUTPUT_VARIABLE} "") + set(REMAINING ${INTVALUE}) + while(REMAINING) + math(EXPR REMAINDER "${REMAINING}%16") + inttohex(${REMAINDER} HEXCHAR) + math(EXPR REMAINING "${REMAINING}/16") + set(${OUTPUT_VARIABLE} "${HEXCHAR}${${OUTPUT_VARIABLE}}") + endwhile() +endmacro() + +today(KERNEL_VERSION_BUILD) + +set(KERNEL_VERSION_MAJOR "0") +set(KERNEL_VERSION_MINOR "4") +set(KERNEL_VERSION_PATCH_LEVEL "0") +set(COPYRIGHT_YEAR "2011") +# KERNEL_VERSION_BUILD_TYPE is "SVN", "RC1", "RC2" or "" (for the release) +set(KERNEL_VERSION_BUILD_TYPE "SVN") + + +set(KERNEL_VERSION "${KERNEL_VERSION_MAJOR}.${KERNEL_VERSION_MINOR}") +if(KERNEL_VERSION_PATCH_LEVEL) + set(KERNEL_VERSION "${KERNEL_VERSION}.${KERNEL_VERSION_PATCH_LEVEL}-${KERNEL_VERSION_BUILD_TYPE}") +else() + set(KERNEL_VERSION "${KERNEL_VERSION}-${KERNEL_VERSION_BUILD_TYPE}") +endif() + +math(EXPR REACTOS_DLL_VERSION_MAJOR "${KERNEL_VERSION_MAJOR}+42") +set(DLL_VERSION_STR "${REACTOS_DLL_VERSION_MAJOR}.${KERNEL_VERSION_MINOR}-${KERNEL_VERSION_BUILD_TYPE}") + +# get svn revision number +set(REVISION "-rUNKNOWN") +set(KERNEL_VERSION_BUILD_HEX "0") +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn") + find_package(Subversion) + if(Subversion_FOUND) + subversion_wc_info(${CMAKE_CURRENT_SOURCE_DIR} SVNINFO) + if(SVNINFO_WC_REVISION) + set(REVISION "-r${SVNINFO_WC_REVISION}") + converttohex(${SVNINFO_WC_REVISION} KERNEL_VERSION_BUILD_HEX) + endif() + endif() +endif() + +configure_file(include/reactos/version.h.cmake ${REACTOS_BINARY_DIR}/include/reactos/version.h) +configure_file(include/reactos/buildno.h.cmake ${REACTOS_BINARY_DIR}/include/reactos/buildno.h) diff --git a/lib/3rdparty/bzip2/CMakeLists.txt b/lib/3rdparty/bzip2/CMakeLists.txt index ee76113cfc4..a3624108d97 100644 --- a/lib/3rdparty/bzip2/CMakeLists.txt +++ b/lib/3rdparty/bzip2/CMakeLists.txt @@ -16,5 +16,6 @@ add_library(bzip2 SHARED ${SOURCE}) set_module_type(bzip2 kernelmodedriver) add_importlibs(bzip2 ntoskrnl) +target_link_libraries(bzip2 libcntpr) set_target_properties(bzip2 PROPERTIES OUTPUT_NAME "unbzip2") diff --git a/lib/3rdparty/fullfat/CMakeLists.txt b/lib/3rdparty/fullfat/CMakeLists.txt index 657abdd3bb4..a25ae581a36 100644 --- a/lib/3rdparty/fullfat/CMakeLists.txt +++ b/lib/3rdparty/fullfat/CMakeLists.txt @@ -18,3 +18,5 @@ list(APPEND SOURCE ff_time.c) add_library(fullfat ${SOURCE}) + +add_dependencies(fullfat bugcodes) diff --git a/lib/3rdparty/libwine/CMakeLists.txt b/lib/3rdparty/libwine/CMakeLists.txt index 1a243a2da2a..6450dd2b03b 100644 --- a/lib/3rdparty/libwine/CMakeLists.txt +++ b/lib/3rdparty/libwine/CMakeLists.txt @@ -6,7 +6,8 @@ list(APPEND SOURCE config.c debug_ros.c loader.c - string.c) +# string.c implements _stricmp, already shipped with crt +) add_library(wine ${SOURCE}) diff --git a/lib/3rdparty/mingw/tlssup.c b/lib/3rdparty/mingw/tlssup.c index 1c32d0d62a6..70fdc6ba224 100644 --- a/lib/3rdparty/mingw/tlssup.c +++ b/lib/3rdparty/mingw/tlssup.c @@ -99,6 +99,7 @@ BOOL WINAPI __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) { _PVFV *pfunc; + uintptr_t ps; #ifndef _WIN64 if (_winmajor < 4) @@ -135,8 +136,11 @@ __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) return TRUE; } - for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc) + ps = (uintptr_t) &__xd_a; + ps += sizeof (uintptr_t); + for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t)) { + pfunc = (_PVFV *) ps; if (*pfunc != NULL) (*pfunc)(); } diff --git a/lib/atl/atlcom.h b/lib/atl/atlcom.h index cc0b8737ca8..f4a13e5540c 100644 --- a/lib/atl/atlcom.h +++ b/lib/atl/atlcom.h @@ -321,7 +321,7 @@ public: \ typedef x _ComMapClass; \ HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject) \ { \ - return InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \ + return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \ } \ const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() \ { \ diff --git a/lib/cmlib/CMakeLists.txt b/lib/cmlib/CMakeLists.txt index 38c1b530a59..707707b28a2 100644 --- a/lib/cmlib/CMakeLists.txt +++ b/lib/cmlib/CMakeLists.txt @@ -15,6 +15,7 @@ list(APPEND SOURCE if(CMAKE_CROSSCOMPILING) add_library(cmlib ${SOURCE}) add_dependencies(cmlib bugcodes) + add_pch(cmlib cmlib.h) else() add_definitions( -D__NO_CTYPE_INLINES diff --git a/lib/cmlib/cmlib.h b/lib/cmlib/cmlib.h index 5fb85060130..5a4abbfeff9 100644 --- a/lib/cmlib/cmlib.h +++ b/lib/cmlib/cmlib.h @@ -5,8 +5,6 @@ * Copyright 2001 - 2005 Eric Kohl */ -#pragma once - // // Debug support switch // diff --git a/lib/dnslib/CMakeLists.txt b/lib/dnslib/CMakeLists.txt index f726f758e17..eae9061928a 100644 --- a/lib/dnslib/CMakeLists.txt +++ b/lib/dnslib/CMakeLists.txt @@ -23,4 +23,5 @@ list(APPEND SOURCE utf8.c) add_library(dnslib ${SOURCE}) -add_dependencies(dnslib psdk) \ No newline at end of file +add_pch(dnslib inc/precomp.h) +add_dependencies(dnslib psdk) diff --git a/lib/drivers/ip/CMakeLists.txt b/lib/drivers/ip/CMakeLists.txt index 87962656704..eb480c75804 100644 --- a/lib/drivers/ip/CMakeLists.txt +++ b/lib/drivers/ip/CMakeLists.txt @@ -33,4 +33,5 @@ list(APPEND SOURCE transport/udp/udp.c) add_library(ip ${SOURCE}) +add_pch(ip precomp.h) add_dependencies(ip bugcodes) diff --git a/lib/drivers/ip/network/ip.c b/lib/drivers/ip/network/ip.c index c1d83ba63c2..72998e5c663 100644 --- a/lib/drivers/ip/network/ip.c +++ b/lib/drivers/ip/network/ip.c @@ -279,6 +279,11 @@ BOOLEAN IPRegisterInterface( IF->Index = ChosenIndex; + if (!AddrIsUnspecified(&IF->Unicast)) + { + IPAddInterfaceRoute(IF); + } + /* Add interface to the global interface list */ TcpipInterlockedInsertTailList(&InterfaceListHead, &IF->ListEntry, diff --git a/lib/drivers/ip/network/loopback.c b/lib/drivers/ip/network/loopback.c index 18054bcf50e..489f23f7722 100644 --- a/lib/drivers/ip/network/loopback.c +++ b/lib/drivers/ip/network/loopback.c @@ -125,7 +125,6 @@ NDIS_STATUS LoopRegisterAdapter( AddrInitIPv4(&Loopback->Broadcast, LOOPBACK_BCASTADDR_IPv4); IPRegisterInterface(Loopback); - IPAddInterfaceRoute(Loopback); TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); diff --git a/lib/drivers/ip/network/receive.c b/lib/drivers/ip/network/receive.c index a7908ef6460..47520685c58 100644 --- a/lib/drivers/ip/network/receive.c +++ b/lib/drivers/ip/network/receive.c @@ -293,6 +293,9 @@ VOID ProcessFragment( TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n")); /* We have a reassembly structure */ TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql); + + /* Reset the timeout since we received a fragment */ + IPDR->TimeoutCount = 0; } else { TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n")); diff --git a/lib/drivers/ip/precomp.h b/lib/drivers/ip/precomp.h new file mode 100644 index 00000000000..354addeba8d --- /dev/null +++ b/lib/drivers/ip/precomp.h @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/lib/drivers/ip/transport/tcp/tcp.c b/lib/drivers/ip/transport/tcp/tcp.c index 5b087f35f3f..cd00faf1801 100644 --- a/lib/drivers/ip/transport/tcp/tcp.c +++ b/lib/drivers/ip/transport/tcp/tcp.c @@ -275,6 +275,8 @@ NTSTATUS TCPConnect } bindaddr.addr = NCE->Interface->Unicast.Address.IPv4Address; + + DbgPrint("Connect - Explicit bind on port %d returned 0x%x\n", Connection->AddressFile->Port, Status); } else { diff --git a/lib/drivers/sound/CMakeLists.txt b/lib/drivers/sound/CMakeLists.txt index 17bc771d157..3865a53aaf8 100644 --- a/lib/drivers/sound/CMakeLists.txt +++ b/lib/drivers/sound/CMakeLists.txt @@ -1,5 +1,5 @@ -add_subdirectory(legacy) +#add_subdirectory(legacy) add_subdirectory(mmebuddy) add_subdirectory(mment4) add_subdirectory(mmixer) diff --git a/lib/drivers/sound/mmebuddy/CMakeLists.txt b/lib/drivers/sound/mmebuddy/CMakeLists.txt index 19af9789f1c..a4c04f261ed 100644 --- a/lib/drivers/sound/mmebuddy/CMakeLists.txt +++ b/lib/drivers/sound/mmebuddy/CMakeLists.txt @@ -26,4 +26,5 @@ list(APPEND SOURCE wave/streaming.c) add_library(mmebuddy ${SOURCE}) +add_pch(mmebuddy precomp.h) add_dependencies(mmebuddy psdk) diff --git a/lib/drivers/sound/mmebuddy/auxiliary/auxMessage.c b/lib/drivers/sound/mmebuddy/auxiliary/auxMessage.c index 9cfa0d941e6..6a164de0c8b 100644 --- a/lib/drivers/sound/mmebuddy/auxiliary/auxMessage.c +++ b/lib/drivers/sound/mmebuddy/auxiliary/auxMessage.c @@ -9,14 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include -#include - -#include +#include "precomp.h" /* Standard MME driver entry-point for messages relating to auxiliary devices. diff --git a/lib/drivers/sound/mmebuddy/capabilities.c b/lib/drivers/sound/mmebuddy/capabilities.c index edf75990783..aa257078fa4 100644 --- a/lib/drivers/sound/mmebuddy/capabilities.c +++ b/lib/drivers/sound/mmebuddy/capabilities.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* Obtains the capabilities of a sound device. This routine ensures that the diff --git a/lib/drivers/sound/mmebuddy/deviceinstance.c b/lib/drivers/sound/mmebuddy/deviceinstance.c index 0558b2b4501..33f23e3105f 100644 --- a/lib/drivers/sound/mmebuddy/deviceinstance.c +++ b/lib/drivers/sound/mmebuddy/deviceinstance.c @@ -8,10 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include +#include "precomp.h" /* Restrain ourselves from flooding the kernel device! diff --git a/lib/drivers/sound/mmebuddy/devicelist.c b/lib/drivers/sound/mmebuddy/devicelist.c index e4e4791012e..c2003927320 100644 --- a/lib/drivers/sound/mmebuddy/devicelist.c +++ b/lib/drivers/sound/mmebuddy/devicelist.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" ULONG SoundDeviceCounts[SOUND_DEVICE_TYPES]; PSOUND_DEVICE SoundDeviceListHeads[SOUND_DEVICE_TYPES]; diff --git a/lib/drivers/sound/mmebuddy/functiontable.c b/lib/drivers/sound/mmebuddy/functiontable.c index 18d7d765299..ce5b38b2431 100644 --- a/lib/drivers/sound/mmebuddy/functiontable.c +++ b/lib/drivers/sound/mmebuddy/functiontable.c @@ -10,10 +10,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include +#include "precomp.h" /* Attaches a function table to a sound device. Any NULL entries in this diff --git a/lib/drivers/sound/mmebuddy/kernel.c b/lib/drivers/sound/mmebuddy/kernel.c index 62766b0c6a7..63b57a41f96 100644 --- a/lib/drivers/sound/mmebuddy/kernel.c +++ b/lib/drivers/sound/mmebuddy/kernel.c @@ -9,11 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include +#include "precomp.h" /* Wraps around CreateFile in order to provide a simpler interface tailored diff --git a/lib/drivers/sound/mmebuddy/midi/midMessage.c b/lib/drivers/sound/mmebuddy/midi/midMessage.c index 95738d78d89..d9a9f9c5273 100644 --- a/lib/drivers/sound/mmebuddy/midi/midMessage.c +++ b/lib/drivers/sound/mmebuddy/midi/midMessage.c @@ -9,14 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include -#include - -#include +#include "precomp.h" /* Standard MME driver entry-point for messages relating to MIDI input. diff --git a/lib/drivers/sound/mmebuddy/midi/modMessage.c b/lib/drivers/sound/mmebuddy/midi/modMessage.c index d189b03fd1b..e6c09004a5b 100644 --- a/lib/drivers/sound/mmebuddy/midi/modMessage.c +++ b/lib/drivers/sound/mmebuddy/midi/modMessage.c @@ -9,14 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include -#include - -#include +#include "precomp.h" /* Standard MME driver entry-point for messages relating to MIDI output. diff --git a/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c b/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c index 7652d9ef7ea..aa196993b6d 100644 --- a/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c +++ b/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c @@ -9,14 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include -#include -#undef NDEBUG -#include +#include "precomp.h" MMRESULT MmeGetLineInfo( diff --git a/lib/drivers/sound/mmebuddy/mmewrap.c b/lib/drivers/sound/mmebuddy/mmewrap.c index 5b651540bde..bf850d24257 100644 --- a/lib/drivers/sound/mmebuddy/mmewrap.c +++ b/lib/drivers/sound/mmebuddy/mmewrap.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* diff --git a/lib/drivers/sound/mmebuddy/precomp.h b/lib/drivers/sound/mmebuddy/precomp.h new file mode 100644 index 00000000000..c1fa03c9264 --- /dev/null +++ b/lib/drivers/sound/mmebuddy/precomp.h @@ -0,0 +1,6 @@ +#include +#include +#include +#include +#include +#include diff --git a/lib/drivers/sound/mmebuddy/reentrancy.c b/lib/drivers/sound/mmebuddy/reentrancy.c index 16ed1a1f9bb..8fc41bb10af 100644 --- a/lib/drivers/sound/mmebuddy/reentrancy.c +++ b/lib/drivers/sound/mmebuddy/reentrancy.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" HANDLE EntrypointMutexes[SOUND_DEVICE_TYPES]; diff --git a/lib/drivers/sound/mmebuddy/thread.c b/lib/drivers/sound/mmebuddy/thread.c index 625cf9654de..484758279c0 100644 --- a/lib/drivers/sound/mmebuddy/thread.c +++ b/lib/drivers/sound/mmebuddy/thread.c @@ -8,11 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include +#include "precomp.h" DWORD WINAPI SoundThreadMain( diff --git a/lib/drivers/sound/mmebuddy/utility.c b/lib/drivers/sound/mmebuddy/utility.c index 0a53fdf43a8..18c2d7638b7 100644 --- a/lib/drivers/sound/mmebuddy/utility.c +++ b/lib/drivers/sound/mmebuddy/utility.c @@ -8,11 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include +#include "precomp.h" static HANDLE ProcessHeapHandle = NULL; static UINT CurrentAllocations = 0; diff --git a/lib/drivers/sound/mmebuddy/wave/format.c b/lib/drivers/sound/mmebuddy/wave/format.c index 34541c4fa0c..b3076b717cc 100644 --- a/lib/drivers/sound/mmebuddy/wave/format.c +++ b/lib/drivers/sound/mmebuddy/wave/format.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" MMRESULT QueryWaveDeviceFormatSupport( diff --git a/lib/drivers/sound/mmebuddy/wave/header.c b/lib/drivers/sound/mmebuddy/wave/header.c index 998edef57af..bb80270f308 100644 --- a/lib/drivers/sound/mmebuddy/wave/header.c +++ b/lib/drivers/sound/mmebuddy/wave/header.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* diff --git a/lib/drivers/sound/mmebuddy/wave/streaming.c b/lib/drivers/sound/mmebuddy/wave/streaming.c index d892f2d1f36..3a4cabc9385 100644 --- a/lib/drivers/sound/mmebuddy/wave/streaming.c +++ b/lib/drivers/sound/mmebuddy/wave/streaming.c @@ -8,12 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* diff --git a/lib/drivers/sound/mmebuddy/wave/widMessage.c b/lib/drivers/sound/mmebuddy/wave/widMessage.c index 6584d3d7bac..81fd344a413 100644 --- a/lib/drivers/sound/mmebuddy/wave/widMessage.c +++ b/lib/drivers/sound/mmebuddy/wave/widMessage.c @@ -9,14 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include -#include - -#include +#include "precomp.h" /* Standard MME driver entry-point for messages relating to wave audio diff --git a/lib/drivers/sound/mmebuddy/wave/wodMessage.c b/lib/drivers/sound/mmebuddy/wave/wodMessage.c index a1202a8e5cc..e73bdf0ecc8 100644 --- a/lib/drivers/sound/mmebuddy/wave/wodMessage.c +++ b/lib/drivers/sound/mmebuddy/wave/wodMessage.c @@ -9,14 +9,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include - -#include -#include - -#include +#include "precomp.h" #if 0 MMRESULT HelloWorld(PSOUND_DEVICE_INSTANCE Instance, PVOID String) diff --git a/lib/drivers/sound/mment4/CMakeLists.txt b/lib/drivers/sound/mment4/CMakeLists.txt index da02da9f7f3..96ab5293d76 100644 --- a/lib/drivers/sound/mment4/CMakeLists.txt +++ b/lib/drivers/sound/mment4/CMakeLists.txt @@ -11,4 +11,5 @@ list(APPEND SOURCE control.c) add_library(mment4 ${SOURCE}) +add_pch(mment4 precomp.h) add_dependencies(mment4 psdk) diff --git a/lib/drivers/sound/mment4/control.c b/lib/drivers/sound/mment4/control.c index 077620bf7ec..66a5c0991c7 100644 --- a/lib/drivers/sound/mment4/control.c +++ b/lib/drivers/sound/mment4/control.c @@ -9,14 +9,7 @@ */ #define NDEBUG - -#include -#include -#include -#include -#include -#include -#include +#include "precomp.h" /* Convenience routine for getting the path of a device and opening it. diff --git a/lib/drivers/sound/mment4/detect.c b/lib/drivers/sound/mment4/detect.c index 06d03411d1d..dd5d9ac2410 100644 --- a/lib/drivers/sound/mment4/detect.c +++ b/lib/drivers/sound/mment4/detect.c @@ -11,15 +11,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include -#include -#include - -#include -#include +#include "precomp.h" /* This is the "nice" way to discover audio devices in NT4 - go into the diff --git a/lib/drivers/sound/mment4/precomp.h b/lib/drivers/sound/mment4/precomp.h new file mode 100644 index 00000000000..cece5d1ea25 --- /dev/null +++ b/lib/drivers/sound/mment4/precomp.h @@ -0,0 +1,8 @@ +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/lib/drivers/sound/mment4/registry.c b/lib/drivers/sound/mment4/registry.c index a606ef77736..aa6dbeac678 100644 --- a/lib/drivers/sound/mment4/registry.c +++ b/lib/drivers/sound/mment4/registry.c @@ -8,16 +8,7 @@ * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) */ -#include -#include -#include -#include - -#include -#include - -#include -#include +#include "precomp.h" /* Open the parameters key of a sound driver. diff --git a/lib/drivers/sound/mmixer/CMakeLists.txt b/lib/drivers/sound/mmixer/CMakeLists.txt index 4edfc124e47..213b0800bdd 100644 --- a/lib/drivers/sound/mmixer/CMakeLists.txt +++ b/lib/drivers/sound/mmixer/CMakeLists.txt @@ -15,5 +15,6 @@ list(APPEND SOURCE topology.c) add_library(mmixer ${SOURCE}) +add_pch(mmixer priv.h) add_dependencies(mmixer bugcodes) diff --git a/lib/drivers/sound/mmixer/priv.h b/lib/drivers/sound/mmixer/priv.h index 3746f6d247b..d5446b81b37 100644 --- a/lib/drivers/sound/mmixer/priv.h +++ b/lib/drivers/sound/mmixer/priv.h @@ -1,5 +1,3 @@ -#pragma once - #include #include diff --git a/lib/drivers/sound/soundblaster/CMakeLists.txt b/lib/drivers/sound/soundblaster/CMakeLists.txt index 96648442ea2..eaf49f91706 100644 --- a/lib/drivers/sound/soundblaster/CMakeLists.txt +++ b/lib/drivers/sound/soundblaster/CMakeLists.txt @@ -13,4 +13,5 @@ list(APPEND SOURCE mixer.c) add_library(soundblaster ${SOURCE}) +add_pch(soundblaster precomp.h) add_dependencies(soundblaster bugcodes) diff --git a/lib/drivers/sound/soundblaster/dsp_io.c b/lib/drivers/sound/soundblaster/dsp_io.c index 320efc1cab0..9dac6419554 100644 --- a/lib/drivers/sound/soundblaster/dsp_io.c +++ b/lib/drivers/sound/soundblaster/dsp_io.c @@ -13,11 +13,7 @@ Functions documented in sbdsp.h */ -#include -#include - -#include -#include +#include "precomp.h" NTSTATUS SbDspReset( diff --git a/lib/drivers/sound/soundblaster/mixer.c b/lib/drivers/sound/soundblaster/mixer.c index c6f9197eec0..3301317b8bc 100644 --- a/lib/drivers/sound/soundblaster/mixer.c +++ b/lib/drivers/sound/soundblaster/mixer.c @@ -18,10 +18,7 @@ The I/O switches are used for muting/unmuting mic, etc. */ -#include -#include - -#include +#include "precomp.h" VOID SbMixerReset(IN PUCHAR BasePort) diff --git a/lib/drivers/sound/soundblaster/precomp.h b/lib/drivers/sound/soundblaster/precomp.h new file mode 100644 index 00000000000..a6b29209b61 --- /dev/null +++ b/lib/drivers/sound/soundblaster/precomp.h @@ -0,0 +1,4 @@ +#include +#include +#include +#include diff --git a/lib/drivers/sound/soundblaster/rate.c b/lib/drivers/sound/soundblaster/rate.c index e539e7ef14c..6855f61a5cf 100644 --- a/lib/drivers/sound/soundblaster/rate.c +++ b/lib/drivers/sound/soundblaster/rate.c @@ -13,10 +13,7 @@ Functions documented in sbdsp.h */ -#include -#include - -#include +#include "precomp.h" BOOLEAN SbDspIsValidInputRate( diff --git a/lib/drivers/sound/soundblaster/speaker.c b/lib/drivers/sound/soundblaster/speaker.c index a7dc60540cf..a74a0b5d99f 100644 --- a/lib/drivers/sound/soundblaster/speaker.c +++ b/lib/drivers/sound/soundblaster/speaker.c @@ -13,10 +13,7 @@ Functions documented in sbdsp.h */ -#include -#include - -#include +#include "precomp.h" NTSTATUS SbDspEnableSpeaker( diff --git a/lib/drivers/sound/soundblaster/version.c b/lib/drivers/sound/soundblaster/version.c index 045d1662a29..c6f95fcd5dd 100644 --- a/lib/drivers/sound/soundblaster/version.c +++ b/lib/drivers/sound/soundblaster/version.c @@ -13,10 +13,7 @@ Functions documented in sbdsp.h */ -#include -#include - -#include +#include "precomp.h" NTSTATUS SbDspGetVersion( diff --git a/lib/epsapi/CMakeLists.txt b/lib/epsapi/CMakeLists.txt index 4eb87dfe28a..bbbeb7dd8b5 100644 --- a/lib/epsapi/CMakeLists.txt +++ b/lib/epsapi/CMakeLists.txt @@ -4,5 +4,5 @@ add_library(epsapi enum/modules.c enum/processes.c) +add_pch(epsapi enum/precomp.h) add_dependencies(epsapi psdk) - diff --git a/lib/epsapi/enum/drivers.c b/lib/epsapi/enum/drivers.c index 179b698f15d..961628da76e 100644 --- a/lib/epsapi/enum/drivers.c +++ b/lib/epsapi/enum/drivers.c @@ -14,16 +14,11 @@ * and improve reusability */ -#define WIN32_NO_STATUS -#include -#define NTOS_MODE_USER -#include +#include "precomp.h" #define NDEBUG #include -#include - NTSTATUS NTAPI PsaEnumerateSystemModules(IN PSYSMOD_ENUM_ROUTINE Callback, IN OUT PVOID CallbackContext) diff --git a/lib/epsapi/enum/modules.c b/lib/epsapi/enum/modules.c index 55915ee594e..f5a3d73d479 100644 --- a/lib/epsapi/enum/modules.c +++ b/lib/epsapi/enum/modules.c @@ -18,16 +18,12 @@ * isolated in its own library to clear the confusion * and improve reusability */ -#define WIN32_NO_STATUS -#include -#define NTOS_MODE_USER -#include + +#include "precomp.h" #define NDEBUG #include -#include - NTSTATUS NTAPI PsaEnumerateProcessModules(IN HANDLE ProcessHandle, IN PPROCMOD_ENUM_ROUTINE Callback, diff --git a/lib/epsapi/enum/precomp.h b/lib/epsapi/enum/precomp.h new file mode 100644 index 00000000000..d53731b1571 --- /dev/null +++ b/lib/epsapi/enum/precomp.h @@ -0,0 +1,6 @@ +#define WIN32_NO_STATUS +#include +#define NTOS_MODE_USER +#include + +#include diff --git a/lib/epsapi/enum/processes.c b/lib/epsapi/enum/processes.c index 45ebb595b1e..3d772d0b5d1 100644 --- a/lib/epsapi/enum/processes.c +++ b/lib/epsapi/enum/processes.c @@ -30,12 +30,8 @@ * isolated in its own library to clear the confusion * and improve reusability */ -#define WIN32_NO_STATUS -#include -#define NTOS_MODE_USER -#include -#include +#include "precomp.h" #define NDEBUG #include diff --git a/lib/fslib/vfatlib/CMakeLists.txt b/lib/fslib/vfatlib/CMakeLists.txt index 675bbbd16af..8dfeaa58a66 100644 --- a/lib/fslib/vfatlib/CMakeLists.txt +++ b/lib/fslib/vfatlib/CMakeLists.txt @@ -12,4 +12,5 @@ list(APPEND SOURCE fat32.c vfatlib.c) add_library(vfatlib ${SOURCE}) +add_pch(vfatlib vfatlib.h) add_dependencies(vfatlib psdk) diff --git a/lib/fslib/vfatxlib/CMakeLists.txt b/lib/fslib/vfatxlib/CMakeLists.txt index 4c66fd64599..1f4e54439d4 100644 --- a/lib/fslib/vfatxlib/CMakeLists.txt +++ b/lib/fslib/vfatxlib/CMakeLists.txt @@ -1,5 +1,7 @@ add_library(vfatxlib fatx.c vfatxlib.c) +add_pch(vfatxlib vfatxlib.h) +target_link_libraries(vfatxlib chkstk) if(NOT MSVC) target_link_libraries(vfatxlib -lgcc) diff --git a/lib/newinflib/CMakeLists.txt b/lib/newinflib/CMakeLists.txt index bc57ae6b649..65b092e11fc 100644 --- a/lib/newinflib/CMakeLists.txt +++ b/lib/newinflib/CMakeLists.txt @@ -11,6 +11,7 @@ if(CMAKE_CROSSCOMPILING) infrosput.c) add_library(inflib ${GLOBAL_FILES} ${SOURCE}) + add_pch(inflib inflib.h) add_dependencies(inflib psdk) else() list(APPEND SOURCE diff --git a/lib/rossym_new/compat.h b/lib/rossym_new/compat.h index 375b498fa3e..80f0e94d0e4 100644 --- a/lib/rossym_new/compat.h +++ b/lib/rossym_new/compat.h @@ -19,6 +19,19 @@ typedef long long s64int; typedef ulong size_t; #endif +DECLSPEC_NORETURN +NTSYSAPI +VOID +NTAPI +RtlRaiseStatus(IN NTSTATUS Status); + +#undef assert +#define assert(x) do { \ + if (!(x)) { \ + werrstr("(%s:%d) assertion " #x " failed\n", __FILE__, __LINE__); \ + RtlRaiseStatus(STATUS_ASSERTION_FAILURE); \ + } \ + } while (0) #define offsetof(x,y) FIELD_OFFSET(x,y) #define nil (0) @@ -32,7 +45,13 @@ void *RosSymRealloc(void *mem, ulong newsize); void xfree(void *v); #define werrstr(str, ...) DPRINT(str "\n" ,##__VA_ARGS__) -//#define werrstr(x, ...) printf("(%s:%d) " x "\n",__FILE__,__LINE__,##__VA_ARGS__) +#if 0 +#ifdef NDEBUG +#define werrstr(x, ...) +#else +#define werrstr(x, ...) printf("(%s:%d) " x "\n",__FILE__,__LINE__,##__VA_ARGS__) +#endif +#endif #define malloc(x) RosSymAllocMem(x) #define mallocz(x,y) RosSymAllocMemZero(x,y) diff --git a/lib/rossym_new/dwarf.h b/lib/rossym_new/dwarf.h index 7308d7deab0..3d1101e2e99 100644 --- a/lib/rossym_new/dwarf.h +++ b/lib/rossym_new/dwarf.h @@ -483,5 +483,6 @@ struct DwarfStack DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong); int dwarfgetinfounit(Dwarf*, ulong, DwarfBlock*); +void dwarfdumpsym(Dwarf *d, DwarfSym *s); #define MAXIMUM_DWARF_NAME_SIZE 64 diff --git a/lib/rossym_new/dwarfabbrev.c b/lib/rossym_new/dwarfabbrev.c index 365d44232d4..a9d3c49b027 100644 --- a/lib/rossym_new/dwarfabbrev.c +++ b/lib/rossym_new/dwarfabbrev.c @@ -83,7 +83,7 @@ parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pna if(num == 0) break; tag = dwarfget128(&b); - DPRINT("num %d tag %x @ %x", num, tag, b.p - d->abbrev.data); + werrstr("abbrev: num %d tag %x @ %x", num, tag, b.p - d->abbrev.data); haskids = dwarfget1(&b); for(i=0;; i++){ name = dwarfget128(&b); @@ -120,11 +120,12 @@ findabbrev(DwarfAbbrev *a, int na, ulong num) { int i; - for(i=0; iattrs.name, name); if(s->attrs.name && strcmp(s->attrs.name, name) == 0) return 0; + } werrstr("symbol '%s' not found", name); return -1; } @@ -188,7 +190,10 @@ dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s) DwarfSym compunit = { }; if(dwarfenumunit(d, unit, &compunit) < 0) return -1; + werrstr("dwarfseeksym: unit %x off %x\n", unit, off); + s->b.d = d; s->b.p = d->info.data + unit + off; + s->b.ep = compunit.b.ep; if(dwarfnextsymat(d, &compunit, s) == -1) return -1; werrstr("dwarfseeksym: unit %x off %x, tag %x", unit, off, s->attrs.tag); @@ -238,7 +243,7 @@ dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s) return -1; } s->b.ep = s->b.p+len; - if((i=dwarfget2(&s->b)) != 2) + if((i=dwarfget2(&s->b)) > 4) goto badheader; aoff = dwarfget4(&s->b); s->b.addrsize = dwarfget1(&s->b); @@ -258,15 +263,19 @@ dwarfnextsym(Dwarf *d, DwarfSym *s) ulong num; DwarfAbbrev *a; + werrstr("sym at %x (left %x)\n", s->b.p - d->info.data, s->b.ep - s->b.p); + num = dwarfget128(&s->b); + werrstr("abbrev num %x\n", num); s->num = num; if(num == 0){ return -1; } a = dwarfgetabbrev(d, s->aoff, num); + werrstr("a %p\n", a); if(a == nil){ - werrstr("getabbrev %ud %ud for %ud,%ud", s->aoff, num, s->unit); + werrstr("getabbrev %x %x for %x", s->aoff, num, s->unit); return -1; } @@ -277,6 +286,7 @@ dwarfnextsym(Dwarf *d, DwarfSym *s) if (s->attrs.haskids) { DwarfSym childSkip = { }; s->childoff = s->b.p - d->info.data; + werrstr("Set childoff at %x\n", s->childoff); int r = dwarfnextsymat(d, s, &childSkip); while (r == 0) { r = dwarfnextsym(d, &childSkip); @@ -316,6 +326,7 @@ dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child) if (!child->b.d) { child->b = parent->b; child->b.p = parent->childoff + parent->b.d->info.data; + werrstr("Rewound to childoff %x\n", parent->childoff); } return dwarfnextsym(d, child); @@ -323,76 +334,78 @@ dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child) typedef struct Parse Parse; struct Parse { + const char *namestr; int name; int off; int haveoff; int type; }; +#define ATTR(x) (#x)+9, x #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x) static Parse plist[] = { /* Font Tab 4 */ - { DwarfAttrAbstractOrigin, OFFSET(abstractorigin), TReference }, - { DwarfAttrAccessibility, OFFSET(accessibility), TConstant }, - { DwarfAttrAddrClass, OFFSET(addrclass), TConstant }, - { DwarfAttrArtificial, OFFSET(isartificial), TFlag }, - { DwarfAttrBaseTypes, OFFSET(basetypes), TReference }, - { DwarfAttrBitOffset, OFFSET(bitoffset), TConstant }, - { DwarfAttrBitSize, OFFSET(bitsize), TConstant }, - { DwarfAttrByteSize, OFFSET(bytesize), TConstant }, - { DwarfAttrCalling, OFFSET(calling), TConstant }, - { DwarfAttrCommonRef, OFFSET(commonref), TReference }, - { DwarfAttrCompDir, OFFSET(compdir), TString }, - { DwarfAttrConstValue, OFFSET(constvalue), TString|TConstant|TBlock }, - { DwarfAttrContainingType, OFFSET(containingtype), TReference }, - { DwarfAttrCount, OFFSET(count), TConstant|TReference }, - { DwarfAttrDataMemberLoc, OFFSET(datamemberloc), TBlock|TConstant|TReference }, - { DwarfAttrDeclColumn, OFFSET(declcolumn), TConstant }, - { DwarfAttrDeclFile, OFFSET(declfile), TConstant }, - { DwarfAttrDeclLine, OFFSET(declline), TConstant }, - { DwarfAttrDeclaration, OFFSET(isdeclaration), TFlag }, - { DwarfAttrDefaultValue, OFFSET(defaultvalue), TReference }, - { DwarfAttrDiscr, OFFSET(discr), TReference }, - { DwarfAttrDiscrList, OFFSET(discrlist), TBlock }, - { DwarfAttrDiscrValue, OFFSET(discrvalue), TConstant }, - { DwarfAttrEncoding, OFFSET(encoding), TConstant }, - { DwarfAttrExternal, OFFSET(isexternal), TFlag }, - { DwarfAttrFrameBase, OFFSET(framebase), TBlock|TConstant }, - { DwarfAttrFriend, OFFSET(friend), TReference }, - { DwarfAttrHighpc, OFFSET(highpc), TAddress }, - { DwarfAttrEntrypc, OFFSET(entrypc), TAddress }, - { DwarfAttrIdentifierCase, OFFSET(identifiercase), TConstant }, - { DwarfAttrImport, OFFSET(import), TReference }, - { DwarfAttrInline, OFFSET(inlined), TConstant }, - { DwarfAttrIsOptional, OFFSET(isoptional), TFlag }, - { DwarfAttrLanguage, OFFSET(language), TConstant }, - { DwarfAttrLocation, OFFSET(location), TReference|TBlock }, - { DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference }, - { DwarfAttrLowpc, OFFSET(lowpc), TAddress }, - { DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant }, - { DwarfAttrName, OFFSET(name), TString }, - { DwarfAttrNamelistItem, OFFSET(namelistitem), TBlock }, - { DwarfAttrOrdering, OFFSET(ordering), TConstant }, - { DwarfAttrPriority, OFFSET(priority), TReference }, - { DwarfAttrProducer, OFFSET(producer), TString }, - { DwarfAttrPrototyped, OFFSET(isprototyped), TFlag }, - { DwarfAttrRanges, OFFSET(ranges), TReference }, - { DwarfAttrReturnAddr, OFFSET(returnaddr), TBlock|TConstant }, - { DwarfAttrSegment, OFFSET(segment), TBlock|TConstant }, - { DwarfAttrSibling, OFFSET(sibling), TReference }, - { DwarfAttrSpecification, OFFSET(specification), TReference }, - { DwarfAttrStartScope, OFFSET(startscope), TConstant }, - { DwarfAttrStaticLink, OFFSET(staticlink), TBlock|TConstant }, - { DwarfAttrStmtList, OFFSET(stmtlist), TConstant }, - { DwarfAttrStrideSize, OFFSET(stridesize), TConstant }, - { DwarfAttrStringLength, OFFSET(stringlength), TBlock|TConstant }, - { DwarfAttrType, OFFSET(type), TReference }, - { DwarfAttrUpperBound, OFFSET(upperbound), TConstant|TReference }, - { DwarfAttrUseLocation, OFFSET(uselocation), TBlock|TConstant }, - { DwarfAttrVarParam, OFFSET(isvarparam), TFlag }, - { DwarfAttrVirtuality, OFFSET(virtuality), TConstant }, - { DwarfAttrVisibility, OFFSET(visibility), TConstant }, - { DwarfAttrVtableElemLoc, OFFSET(vtableelemloc), TBlock|TReference }, + { ATTR(DwarfAttrAbstractOrigin), OFFSET(abstractorigin), TReference }, + { ATTR(DwarfAttrAccessibility), OFFSET(accessibility), TConstant }, + { ATTR(DwarfAttrAddrClass), OFFSET(addrclass), TConstant }, + { ATTR(DwarfAttrBaseTypes), OFFSET(basetypes), TReference }, + { ATTR(DwarfAttrBitOffset), OFFSET(bitoffset), TConstant }, + { ATTR(DwarfAttrBitSize), OFFSET(bitsize), TConstant }, + { ATTR(DwarfAttrByteSize), OFFSET(bytesize), TConstant }, + { ATTR(DwarfAttrCalling), OFFSET(calling), TConstant }, + { ATTR(DwarfAttrCommonRef), OFFSET(commonref), TReference }, + { ATTR(DwarfAttrCompDir), OFFSET(compdir), TString }, + { ATTR(DwarfAttrConstValue), OFFSET(constvalue), TString|TConstant|TBlock }, + { ATTR(DwarfAttrContainingType), OFFSET(containingtype), TReference }, + { ATTR(DwarfAttrCount), OFFSET(count), TConstant|TReference }, + { ATTR(DwarfAttrDataMemberLoc), OFFSET(datamemberloc), TBlock|TConstant|TReference }, + { ATTR(DwarfAttrDeclColumn), OFFSET(declcolumn), TConstant }, + { ATTR(DwarfAttrDeclFile), OFFSET(declfile), TConstant }, + { ATTR(DwarfAttrDeclLine), OFFSET(declline), TConstant }, + { ATTR(DwarfAttrDefaultValue), OFFSET(defaultvalue), TReference }, + { ATTR(DwarfAttrDiscr), OFFSET(discr), TReference }, + { ATTR(DwarfAttrDiscrList), OFFSET(discrlist), TBlock }, + { ATTR(DwarfAttrDiscrValue), OFFSET(discrvalue), TConstant }, + { ATTR(DwarfAttrEncoding), OFFSET(encoding), TConstant }, + { ATTR(DwarfAttrFrameBase), OFFSET(framebase), TBlock|TConstant }, + { ATTR(DwarfAttrFriend), OFFSET(friend), TReference }, + { ATTR(DwarfAttrHighpc), OFFSET(highpc), TAddress }, + { ATTR(DwarfAttrEntrypc), OFFSET(entrypc), TAddress }, + { ATTR(DwarfAttrIdentifierCase), OFFSET(identifiercase), TConstant }, + { ATTR(DwarfAttrImport), OFFSET(import), TReference }, + { ATTR(DwarfAttrInline), OFFSET(inlined), TConstant }, + { ATTR(DwarfAttrArtificial), OFFSET(isartificial), TFlag }, + { ATTR(DwarfAttrDeclaration), OFFSET(isdeclaration), TFlag }, + { ATTR(DwarfAttrExternal), OFFSET(isexternal), TFlag }, + { ATTR(DwarfAttrIsOptional), OFFSET(isoptional), TFlag }, + { ATTR(DwarfAttrPrototyped), OFFSET(isprototyped), TFlag }, + { ATTR(DwarfAttrVarParam), OFFSET(isvarparam), TFlag }, + { ATTR(DwarfAttrLanguage), OFFSET(language), TConstant }, + { ATTR(DwarfAttrLocation), OFFSET(location), TReference|TBlock }, + { ATTR(DwarfAttrLowerBound), OFFSET(lowerbound), TConstant|TReference }, + { ATTR(DwarfAttrLowpc), OFFSET(lowpc), TAddress }, + { ATTR(DwarfAttrMacroInfo), OFFSET(macroinfo), TConstant }, + { ATTR(DwarfAttrName), OFFSET(name), TString }, + { ATTR(DwarfAttrNamelistItem), OFFSET(namelistitem), TBlock }, + { ATTR(DwarfAttrOrdering), OFFSET(ordering), TConstant }, + { ATTR(DwarfAttrPriority), OFFSET(priority), TReference }, + { ATTR(DwarfAttrProducer), OFFSET(producer), TString }, + { ATTR(DwarfAttrRanges), OFFSET(ranges), TReference }, + { ATTR(DwarfAttrReturnAddr), OFFSET(returnaddr), TBlock|TConstant }, + { ATTR(DwarfAttrSegment), OFFSET(segment), TBlock|TConstant }, + { ATTR(DwarfAttrSibling), OFFSET(sibling), TReference }, + { ATTR(DwarfAttrSpecification), OFFSET(specification), TReference }, + { ATTR(DwarfAttrStartScope), OFFSET(startscope), TConstant }, + { ATTR(DwarfAttrStaticLink), OFFSET(staticlink), TBlock|TConstant }, + { ATTR(DwarfAttrStmtList), OFFSET(stmtlist), TConstant }, + { ATTR(DwarfAttrStrideSize), OFFSET(stridesize), TConstant }, + { ATTR(DwarfAttrStringLength), OFFSET(stringlength), TBlock|TConstant }, + { ATTR(DwarfAttrType), OFFSET(type), TReference }, + { ATTR(DwarfAttrUpperBound), OFFSET(upperbound), TConstant|TReference }, + { ATTR(DwarfAttrUseLocation), OFFSET(uselocation), TBlock|TConstant }, + { ATTR(DwarfAttrVirtuality), OFFSET(virtuality), TConstant }, + { ATTR(DwarfAttrVisibility), OFFSET(visibility), TConstant }, + { ATTR(DwarfAttrVtableElemLoc), OFFSET(vtableelemloc), TBlock|TReference }, { } }; @@ -417,6 +430,7 @@ parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAt for(i=0; inattr; i++){ n = a->attr[i].name; f = a->attr[i].form; + werrstr("struct: (@%x) n %x f %x (%d %d)\n", b->p - d->info.data, n, f, ptab[n].haveoff, ptab[n].off); if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0) { if (skipform(d, b, f) < 0) { if(++nbad == 1) @@ -436,11 +450,12 @@ parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAt got = TFlag; else if((ptab[n].type&TString) && getstring(d, b, f, v) >= 0) got = TString; - else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0) + else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0) { got = TBlock; - else { + } else { + werrstr("Skipping form %x\n", f); if(skipform(d, b, f) < 0){ - if(++nbad == 1) + //if(++nbad == 1) werrstr("dwarf parse attrs: cannot skip form %d", f); return -1; } @@ -451,6 +466,10 @@ parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAt #endif *((uchar*)attrs+ptab[n].haveoff) = got; } + + if (attrs->have.name) + werrstr("%s: tag %x kids %d (last %x)\n", attrs->name, attrs->tag, attrs->haskids, b->p - b->d->info.data); + return 0; } @@ -651,6 +670,7 @@ int dwarfgetarg(Dwarf *d, const char *name, DwarfBuf *buf, ulong cfa, PROSSYM_RE int ret = 0; DwarfStack stack = { }; stackinit(&stack); + stackpush(&stack, cfa); while (buf->p < buf->ep) { int opcode = dwarfget1(buf); werrstr("opcode %x", opcode); @@ -951,6 +971,25 @@ int dwarfargvalue(Dwarf *d, DwarfSym *proc, ulong pc, ulong cfa, PROSSYM_REGISTE return 0; } +void +dwarfdumpsym(Dwarf *d, DwarfSym *s) +{ + int i, j; + werrstr("tag %x\n", s->attrs.tag); + for (j = 0; plist[j].name; j++) { + char *have = ((char*)&s->attrs) + plist[j].haveoff; + char *attr = ((char*)&s->attrs) + plist[j].off; + if (*have == TString) { + char *str = *((char **)attr); + werrstr("%s: %s\n", plist[j].namestr, str); + } else if (*have == TReference) { + DwarfVal *val = ((DwarfVal*)attr); + werrstr("%s: %x:%x\n", plist[j].namestr, val->b.data, val->b.len); + } else if (*have) + werrstr("%s: (%x)\n", plist[j].namestr, *have); + } +} + int dwarfgetparams(Dwarf *d, DwarfSym *s, ulong pc, int pnum, DwarfParam *paramblocks) { diff --git a/lib/rossym_new/dwarfopen.c b/lib/rossym_new/dwarfopen.c index b3ea2cd18d6..bcb0429ab40 100644 --- a/lib/rossym_new/dwarfopen.c +++ b/lib/rossym_new/dwarfopen.c @@ -30,10 +30,10 @@ dwarfopen(Pe *pe) if(pe->loadsection(pe, ".debug_abbrev", &d->abbrev) < 0 || pe->loadsection(pe, ".debug_aranges", &d->aranges) < 0 || pe->loadsection(pe, ".debug_line", &d->line) < 0 - || pe->loadsection(pe, ".debug_pubnames", &d->pubnames) < 0 || pe->loadsection(pe, ".debug_info", &d->info) < 0 || pe->loadsection(pe, ".debug_loc", &d->loc) < 0) goto err; + pe->loadsection(pe, ".debug_pubnames", &d->pubnames); pe->loadsection(pe, ".debug_frame", &d->frame); pe->loadsection(pe, ".debug_ranges", &d->ranges); pe->loadsection(pe, ".debug_str", &d->str); diff --git a/lib/rossym_new/find.c b/lib/rossym_new/find.c index 9cc5aeeeece..beb6f170eea 100644 --- a/lib/rossym_new/find.c +++ b/lib/rossym_new/find.c @@ -128,4 +128,136 @@ RosSymGetAddressInformation return TRUE; } +VOID +RosSymFreeAggregate(PROSSYM_AGGREGATE Aggregate) +{ + int i; + for (i = 0; i < Aggregate->NumElements; i++) { + free(Aggregate->Elements[i].Name); + free(Aggregate->Elements[i].Type); + } + free(Aggregate->Elements); +} + +BOOLEAN +RosSymAggregate(PROSSYM_INFO RosSymInfo, PCHAR Type, PROSSYM_AGGREGATE Aggregate) +{ + char *tchar; + ulong unit, typeoff = 0; + DwarfSym type = { }; + // Get the first unit + if (dwarfaddrtounit(RosSymInfo, RosSymInfo->pe->codestart + RosSymInfo->pe->imagebase, &unit) == -1) + return FALSE; + + if (Type[0] == '#') { + for (tchar = Type + 1; *tchar; tchar++) { + typeoff *= 10; + typeoff += *tchar - '0'; + } + if (dwarfseeksym(RosSymInfo, unit, typeoff, &type) == -1) + return FALSE; + } else if (dwarflookupnameinunit(RosSymInfo, unit, Type, &type) != 0 || + (type.attrs.tag != TagStructType && type.attrs.tag != TagUnionType)) + return FALSE; + + DwarfSym element = { }, inner = { }; + int count = 0; + + werrstr("type %s (want %s) type %x\n", type.attrs.name, Type, type.attrs.type); + + if (type.attrs.have.type) { + if (dwarfseeksym(RosSymInfo, unit, type.attrs.type, &inner) == -1) + return FALSE; + type = inner; + } + + werrstr("finding members %d\n", type.attrs.haskids); + while (dwarfnextsymat(RosSymInfo, &type, &element) != -1) { + if (element.attrs.have.name) + werrstr("%x %s\n", element.attrs.tag, element.attrs.name); + if (element.attrs.tag == TagMember) count++; + } + + werrstr("%d members\n", count); + + if (!count) return FALSE; + memset(&element, 0, sizeof(element)); + Aggregate->NumElements = count; + Aggregate->Elements = malloc(sizeof(ROSSYM_AGGREGATE_MEMBER) * count); + count = 0; + werrstr("Enumerating %s\n", Type); + while (dwarfnextsymat(RosSymInfo, &type, &element) != -1) { + memset(&Aggregate->Elements[count], 0, sizeof(*Aggregate->Elements)); + if (element.attrs.tag == TagMember) { + if (element.attrs.have.name) { + Aggregate->Elements[count].Name = malloc(strlen(element.attrs.name) + 1); + strcpy(Aggregate->Elements[count].Name, element.attrs.name); + } + Aggregate->Elements[count].TypeId = element.attrs.type; + // Seek our range in loc + DwarfBuf locbuf; + DwarfBuf instream = { }; + + locbuf.d = RosSymInfo; + locbuf.addrsize = RosSymInfo->addrsize; + + if (element.attrs.have.datamemberloc) { + instream = locbuf; + instream.p = element.attrs.datamemberloc.b.data; + instream.ep = element.attrs.datamemberloc.b.data + element.attrs.datamemberloc.b.len; + werrstr("datamemberloc type %x %p:%x\n", + element.attrs.have.datamemberloc, + element.attrs.datamemberloc.b.data, element.attrs.datamemberloc.b.len); + } + + if (dwarfgetarg(RosSymInfo, element.attrs.name, &instream, 0, NULL, &Aggregate->Elements[count].BaseOffset) == -1) + Aggregate->Elements[count].BaseOffset = -1; + werrstr("tag %x name %s base %x type %x\n", + element.attrs.tag, element.attrs.name, + Aggregate->Elements[count].BaseOffset, + Aggregate->Elements[count].TypeId); + count++; + } + } + for (count = 0; count < Aggregate->NumElements; count++) { + memset(&type, 0, sizeof(type)); + memset(&inner, 0, sizeof(inner)); + werrstr("seeking type %x (%s) from %s\n", + Aggregate->Elements[count].TypeId, + Aggregate->Elements[count].Type, + Aggregate->Elements[count].Name); + dwarfseeksym(RosSymInfo, unit, Aggregate->Elements[count].TypeId, &type); + while (type.attrs.have.type && type.attrs.tag != TagPointerType) { + if (dwarfseeksym(RosSymInfo, unit, type.attrs.type, &inner) == -1) + return FALSE; + type = inner; + } + //dwarfdumpsym(RosSymInfo, &type); + if (type.attrs.have.name) { + Aggregate->Elements[count].Type = malloc(strlen(type.attrs.name) + 1); + strcpy(Aggregate->Elements[count].Type, type.attrs.name); + } else { + char strbuf[128] = {'#'}, *bufptr = strbuf + 1; + ulong idcopy = Aggregate->Elements[count].TypeId; + ulong mult = 1; + while (mult * 10 < idcopy) mult *= 10; + while (mult > 0) { + *bufptr++ = '0' + ((idcopy / mult) % 10); + mult /= 10; + } + Aggregate->Elements[count].Type = malloc(strlen(strbuf) + 1); + strcpy(Aggregate->Elements[count].Type, strbuf); + } + if (type.attrs.tag == TagPointerType) + Aggregate->Elements[count].Size = RosSymInfo->addrsize; + else + Aggregate->Elements[count].Size = type.attrs.bytesize; + if (type.attrs.have.bitsize) + Aggregate->Elements[count].Bits = type.attrs.bitsize; + if (type.attrs.have.bitoffset) + Aggregate->Elements[count].FirstBit = type.attrs.bitoffset; + } + return TRUE; +} + /* EOF */ diff --git a/lib/rossym_new/fromfile.c b/lib/rossym_new/fromfile.c index c26ea3e2a80..a3ed16fd946 100644 --- a/lib/rossym_new/fromfile.c +++ b/lib/rossym_new/fromfile.c @@ -146,6 +146,8 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo) pe->sect = SectionHeaders; pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase; pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage; + pe->codestart = NtHeaders.OptionalHeader.BaseOfCode; + pe->datastart = NtHeaders.OptionalHeader.BaseOfData; pe->loadsection = loaddisksection; *RosSymInfo = dwarfopen(pe); diff --git a/lib/rossym_new/pe.c b/lib/rossym_new/pe.c index cace420fec2..63fd9df6906 100644 --- a/lib/rossym_new/pe.c +++ b/lib/rossym_new/pe.c @@ -17,18 +17,18 @@ PeSect *pesection(Pe *pe, const char *name) int i; ANSI_STRING WantName; RtlInitAnsiString(&WantName, name); - DPRINT("Searching for section %s\n", name); + werrstr("Searching for section %s\n", name); for (i = 0; i < pe->nsections; i++) { PANSI_STRING AnsiString = ANSI_NAME_STRING(&pe->sect[i]); if (WantName.Length == AnsiString->Length && !memcmp(AnsiString->Buffer, name, WantName.Length)) { - DPRINT("Found %s (%d) @ %x (%x)\n", name, i, + werrstr("Found %s (%d) @ %x (%x)\n", name, i, ((PCHAR)pe->imagebase)+pe->sect[i].VirtualAddress, pe->sect[i].SizeOfRawData); return &pe->sect[i]; } } - DPRINT("%s not found\n", name); + werrstr("%s not found\n", name); return nil; } @@ -84,11 +84,11 @@ loadmemsection(Pe *pe, char *name, DwarfBlock *b) if((s = pesection(pe, name)) == nil) return -1; - DPRINT("Loading section %s (ImageBase %x RVA %x)\n", name, pe->fd, s->VirtualAddress); + werrstr("Loading section %s (ImageBase %x RVA %x)\n", name, pe->fd, s->VirtualAddress); b->data = RosSymAllocMem(s->SizeOfRawData); b->len = s->SizeOfRawData; PCHAR DataSource = ((char *)pe->fd) + s->VirtualAddress; - DPRINT("Copying to %x from %x (%x)\n", DataSource, b->data, b->len); + werrstr("Copying to %x from %x (%x)\n", DataSource, b->data, b->len); RtlCopyMemory(b->data, DataSource, s->SizeOfRawData); return s->SizeOfRawData; @@ -121,16 +121,16 @@ void xfree(void *v) { ulong pefindrva(struct _IMAGE_SECTION_HEADER *SectionHeaders, int NumberOfSections, ulong TargetPhysical) { int i; - DPRINT("Finding RVA for Physical %x\n", TargetPhysical); + werrstr("Finding RVA for Physical %x\n", TargetPhysical); for (i = 0; i < NumberOfSections; i++) { - DPRINT("Section %d name %s Raw %x Virt %x\n", + werrstr("Section %d name %s Raw %x Virt %x\n", i, ANSI_NAME_STRING(&SectionHeaders[i])->Buffer, SectionHeaders[i].PointerToRawData, SectionHeaders[i].VirtualAddress); if (TargetPhysical >= SectionHeaders[i].PointerToRawData && TargetPhysical < SectionHeaders[i].PointerToRawData + SectionHeaders[i].SizeOfRawData) { - DPRINT("RVA %x\n", TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress); + werrstr("RVA %x\n", TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress); return TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress; } } diff --git a/lib/rossym_new/pe.h b/lib/rossym_new/pe.h index 6b5bbdaa8f4..066d79b2ac6 100644 --- a/lib/rossym_new/pe.h +++ b/lib/rossym_new/pe.h @@ -12,6 +12,7 @@ typedef struct _Pe { u32int (*e4)(const unsigned char *data); u64int (*e8)(const unsigned char *data); ulong imagebase, imagesize, loadbase; + ulong codestart, datastart; int (*loadsection)(struct _Pe *pe, char *name, struct DwarfBlock *b); int nsections; struct _IMAGE_SECTION_HEADER *sect; diff --git a/lib/rtl/actctx.c b/lib/rtl/actctx.c index 71a5459a52c..e607960033f 100644 --- a/lib/rtl/actctx.c +++ b/lib/rtl/actctx.c @@ -2370,26 +2370,32 @@ RtlReleaseActivationContext( HANDLE handle ) } NTSTATUS -NTAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie ) +NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie ) { RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; - + if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) ))) return STATUS_NO_MEMORY; - - frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; + + frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame; frame->ActivationContext = handle; frame->Flags = 0; - - NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame; + + tebAddress->ActivationContextStackPointer->ActiveFrame = frame; RtlAddRefActivationContext( handle ); - + *cookie = (ULONG_PTR)frame; DPRINT( "%p cookie=%lx\n", handle, *cookie ); return STATUS_SUCCESS; } +NTSTATUS +NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie ) +{ + return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie); +} + NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) @@ -2826,7 +2832,10 @@ RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CON frame = &Frame->Frame; if (!frame) + { + DPRINT1("No top frame!\n"); RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); + } /* pop everything up to and including frame */ NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; diff --git a/lib/rtl/generictable.c b/lib/rtl/generictable.c index dee9cf18190..6cb57fd6d7a 100644 --- a/lib/rtl/generictable.c +++ b/lib/rtl/generictable.c @@ -213,7 +213,7 @@ RtlInsertElementGenericTableFull(IN PRTL_GENERIC_TABLE Table, Table->TableRoot = RtlSplay(NewNode); /* Return status */ - if (NewElement) *NewElement = (SearchResult == TableFoundNode); + if (NewElement) *NewElement = (SearchResult != TableFoundNode); /* Return pointer to user data */ return &((PTABLE_ENTRY_HEADER)NewNode)->UserData; @@ -300,7 +300,7 @@ RtlDeleteElementGenericTable(IN PRTL_GENERIC_TABLE Table, /* Get the splay links and table search result immediately */ Result = RtlpFindGenericTableNodeOrParent(Table, Buffer, &NodeOrParent); - if ((Result == TableEmptyTree) || (Result != TableFoundNode)) + if (Result != TableFoundNode) { /* Nothing to delete */ return FALSE; diff --git a/lib/rtl/image.c b/lib/rtl/image.c index ce54a6b4df9..2064dc29db3 100644 --- a/lib/rtl/image.c +++ b/lib/rtl/image.c @@ -120,6 +120,13 @@ LdrVerifyMappedImageMatchesChecksum( return (BOOLEAN)(CalcSum == HeaderSum); #else + /* + * FIXME: Warning, this violates the PE standard and makes ReactOS drivers + * and other system code when normally on Windows they would not, since + * we do not write the checksum in them. + * Our compilers should be made to write out the checksum and this function + * should be enabled as to reject badly checksummed code. + */ return TRUE; #endif } @@ -127,28 +134,124 @@ LdrVerifyMappedImageMatchesChecksum( /* * @implemented */ -PIMAGE_NT_HEADERS +NTSTATUS NTAPI -RtlImageNtHeader(IN PVOID BaseAddress) +RtlImageNtHeaderEx(IN ULONG Flags, + IN PVOID Base, + IN ULONG64 Size, + OUT PIMAGE_NT_HEADERS *OutHeaders) { - PIMAGE_NT_HEADERS NtHeader; - PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress; + PIMAGE_NT_HEADERS NtHeaders; + PIMAGE_DOS_HEADER DosHeader; + BOOLEAN WantsRangeCheck; + + /* You must want NT Headers, no? */ + if (!OutHeaders) return STATUS_INVALID_PARAMETER; + + /* Assume failure */ + *OutHeaders = NULL; - if (DosHeader && SWAPW(DosHeader->e_magic) != IMAGE_DOS_SIGNATURE) + /* Validate Flags */ + if (Flags &~ RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK) { - DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader->e_magic)); - DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR)BaseAddress + SWAPD(DosHeader->e_lfanew))); + DPRINT1("Invalid flag combination... check for new API flags?\n"); + return STATUS_INVALID_PARAMETER; } - else + + /* Validate base */ + if (!(Base) || (Base == (PVOID)-1)) return STATUS_INVALID_PARAMETER; + + /* Check if the caller wants validation */ + WantsRangeCheck = !(Flags & RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK); + if (WantsRangeCheck) { - NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)BaseAddress + SWAPD(DosHeader->e_lfanew)); - if (SWAPD(NtHeader->Signature) == IMAGE_NT_SIGNATURE) - return NtHeader; + /* Make sure the image size is at least big enough for the DOS header */ + if (Size < sizeof(IMAGE_DOS_HEADER)) + { + DPRINT1("Size too small\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } } - return NULL; + /* Check if the DOS Signature matches */ + DosHeader = Base; + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + /* Not a valid COFF */ + DPRINT1("Not an MZ file\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Check if the caller wants validation */ + if (WantsRangeCheck) + { + /* The offset should fit in the passsed-in size */ + if (DosHeader->e_lfanew >= Size) + { + /* Fail */ + DPRINT1("e_lfanew is larger than PE file\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* It shouldn't be past 4GB either */ + if (DosHeader->e_lfanew >= + (MAXULONG - sizeof(IMAGE_DOS_SIGNATURE) - sizeof(IMAGE_FILE_HEADER))) + { + /* Fail */ + DPRINT1("e_lfanew is larger than 4GB\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* And the whole file shouldn't overflow past 4GB */ + if ((DosHeader->e_lfanew + + sizeof(IMAGE_DOS_SIGNATURE) - sizeof(IMAGE_FILE_HEADER)) >= Size) + { + /* Fail */ + DPRINT1("PE is larger than 4GB\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + } + + /* The offset also can't be larger than 256MB, as a hard-coded check */ + if (DosHeader->e_lfanew >= (256 * 1024 * 1024)) + { + /* Fail */ + DPRINT1("PE offset is larger than 256MB\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Now it's safe to get the NT Headers */ + NtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)Base + DosHeader->e_lfanew); + + /* Verify the PE Signature */ + if (NtHeaders->Signature != IMAGE_NT_SIGNATURE) + { + /* Fail */ + DPRINT1("PE signature missing\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + /* Now return success and the NT header */ + *OutHeaders = NtHeaders; + return STATUS_SUCCESS; } + +/* + * @implemented + */ +PIMAGE_NT_HEADERS +NTAPI +RtlImageNtHeader(IN PVOID Base) +{ + PIMAGE_NT_HEADERS NtHeader; + /* Call the new API */ + RtlImageNtHeaderEx(RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK, + Base, + 0, + &NtHeader); + return NtHeader; +} /* * @implemented diff --git a/lib/rtl/path.c b/lib/rtl/path.c index d0b4e21a7a1..6b19214e6d7 100644 --- a/lib/rtl/path.c +++ b/lib/rtl/path.c @@ -25,176 +25,913 @@ /* GLOBALS ********************************************************************/ static const WCHAR DeviceRootW[] = L"\\\\.\\"; +const UNICODE_STRING DeviceRootString = RTL_CONSTANT_STRING(L"\\\\.\\"); -static const UNICODE_STRING _condev = RTL_CONSTANT_STRING(L"\\\\.\\CON"); +const UNICODE_STRING RtlpDosDevicesUncPrefix = RTL_CONSTANT_STRING(L"\\??\\UNC\\"); +const UNICODE_STRING RtlpWin32NtRootSlash = RTL_CONSTANT_STRING(L"\\\\?\\"); +const UNICODE_STRING RtlpDosSlashCONDevice = RTL_CONSTANT_STRING(L"\\\\.\\CON"); +const UNICODE_STRING RtlpDosDevicesPrefix = RTL_CONSTANT_STRING(L"\\??\\"); -static const UNICODE_STRING _lpt = RTL_CONSTANT_STRING(L"LPT"); +const UNICODE_STRING RtlpDosLPTDevice = RTL_CONSTANT_STRING(L"LPT"); +const UNICODE_STRING RtlpDosCOMDevice = RTL_CONSTANT_STRING(L"COM"); +const UNICODE_STRING RtlpDosPRNDevice = RTL_CONSTANT_STRING(L"PRN"); +const UNICODE_STRING RtlpDosAUXDevice = RTL_CONSTANT_STRING(L"AUX"); +const UNICODE_STRING RtlpDosCONDevice = RTL_CONSTANT_STRING(L"CON"); +const UNICODE_STRING RtlpDosNULDevice = RTL_CONSTANT_STRING(L"NUL"); -static const UNICODE_STRING _com = RTL_CONSTANT_STRING(L"COM"); +/* PRIVATE FUNCTIONS **********************************************************/ -static const UNICODE_STRING _prn = RTL_CONSTANT_STRING(L"PRN"); +ULONG +NTAPI +RtlIsDosDeviceName_Ustr(IN PUNICODE_STRING PathString) +{ + UNICODE_STRING PathCopy; + PWCHAR Start, End; + ULONG PathChars, ColonCount = 0; + USHORT ReturnOffset = 0, ReturnLength; + WCHAR c; -static const UNICODE_STRING _aux = RTL_CONSTANT_STRING(L"AUX"); + /* Validate the input */ + if (!PathString) return 0; -static const UNICODE_STRING _con = RTL_CONSTANT_STRING(L"CON"); + /* Check what type of path this is */ + switch (RtlDetermineDosPathNameType_Ustr(PathString)) + { + /* Fail for UNC or unknown paths */ + case RtlPathTypeUnknown: + case RtlPathTypeUncAbsolute: + return 0; + + /* Make special check for the CON device */ + case RtlPathTypeLocalDevice: + if (RtlEqualUnicodeString(PathString, &RtlpDosSlashCONDevice, TRUE)) + { + /* This should return 0x80006 */ + return MAKELONG(RtlpDosCONDevice.Length, DeviceRootString.Length); + } + return 0; -static const UNICODE_STRING _nul = RTL_CONSTANT_STRING(L"NUL"); + default: + break; + } -/* FUNCTIONS *****************************************************************/ + /* Make a copy of the string */ + PathCopy = *PathString; + /* Return if there's no characters */ + PathChars = PathCopy.Length / sizeof(WCHAR); + if (!PathChars) return 0; -/* - * @implemented - */ -ULONG NTAPI RtlGetLongestNtPathLength (VOID) + /* Check for drive path and truncate */ + if (PathCopy.Buffer[PathChars - 1] == L':') + { + /* Fixup the lengths */ + PathCopy.Length -= sizeof(WCHAR); + if (!--PathChars) return 0; + + /* Remember this for later */ + ColonCount = 1; + } + + /* Check for extension or space, and truncate */ + c = PathCopy.Buffer[PathChars - 1]; + do + { + /* Stop if we hit a space or period */ + if ((c != '.') && (c != ' ')) break; + + /* Fixup the lengths and get the next character */ + PathCopy.Length -= sizeof(WCHAR); + if (!--PathChars) c = PathCopy.Buffer[PathChars - 1]; + + /* Remember this for later */ + ColonCount++; + } while (PathChars); + + /* Anything still left? */ + if (PathChars) + { + /* Loop from the end */ + for (End = &PathCopy.Buffer[PathChars - 1]; + End >= PathCopy.Buffer; + --End) + { + /* Check if the character is a path or drive separator */ + c = *End; + if ((c == '\\') || (c == '/') || ((c == ':') && (End == PathCopy.Buffer + 1))) + { + /* Get the next lower case character */ + End++; + c = *End | ' '; // ' ' == ('z' - 'Z') + + /* Check if it's a DOS device (LPT, COM, PRN, AUX, or NUL) */ + if ((End < &PathCopy.Buffer[PathCopy.Length / sizeof(WCHAR)]) && + ((c == 'l') || (c == 'c') || (c == 'p') || (c == 'a') || (c == 'n'))) + { + /* Calculate the offset */ + ReturnOffset = (PCHAR)End - (PCHAR)PathCopy.Buffer; + + /* Build the final string */ + PathCopy.Length -= ReturnOffset; + PathCopy.Length -= (ColonCount * sizeof(WCHAR)); + PathCopy.Buffer = End; + break; + } + } + + return 0; + } + + /* Get the next lower case character and check if it's a DOS device */ + c = *PathCopy.Buffer | ' '; // ' ' == ('z' - 'Z') + if ((c != 'l') && (c != 'c') && (c != 'p') && (c != 'a') && (c != 'n')) + { + /* Not LPT, COM, PRN, AUX, or NUL */ + return 0; + } + } + + /* Now skip past any extra extension or drive letter characters */ + Start = PathCopy.Buffer; + End = &Start[PathChars]; + while (Start < End) + { + c = *Start; + if ((c == '.') || (c == ':')) break; + Start++; + } + + /* And then go backwards to get rid of spaces */ + while ((Start > PathCopy.Buffer) && (Start[-1] == ' ')) --Start; + + /* Finally see how many characters are left, and that's our size */ + PathChars = Start - PathCopy.Buffer; + PathCopy.Length = PathChars * sizeof(WCHAR); + + /* Check if this is a COM or LPT port, which has a digit after it */ + if ((PathChars == 4) && + (iswdigit(PathCopy.Buffer[3]) && (PathCopy.Buffer[3] != '0'))) + { + /* Don't compare the number part, just check for LPT or COM */ + PathCopy.Length -= sizeof(WCHAR); + if ((RtlEqualUnicodeString(&PathCopy, &RtlpDosLPTDevice, TRUE)) || + (RtlEqualUnicodeString(&PathCopy, &RtlpDosCOMDevice, TRUE))) + { + /* Found it */ + ReturnLength = sizeof(L"COM1"); + return MAKELONG(ReturnOffset, ReturnLength); + } + } + else if ((PathChars == 3) && + ((RtlEqualUnicodeString(&PathCopy, &RtlpDosPRNDevice, TRUE)) || + (RtlEqualUnicodeString(&PathCopy, &RtlpDosAUXDevice, TRUE)) || + (RtlEqualUnicodeString(&PathCopy, &RtlpDosNULDevice, TRUE)) || + (RtlEqualUnicodeString(&PathCopy, &RtlpDosCONDevice, TRUE)))) + { + /* Otherwise this was something like AUX, NUL, PRN, or CON */ + ReturnLength = sizeof(L"AUX"); + return MAKELONG(ReturnOffset, ReturnLength); + } + + /* Otherwise, this isn't a valid DOS device */ + return 0; +} + +RTL_PATH_TYPE +NTAPI +RtlDetermineDosPathNameType_Ustr(IN PCUNICODE_STRING PathString) { - return (MAX_PATH + 9); + PWCHAR Path; + ULONG Chars; + + /* Validate the input */ + if (!PathString) return RtlPathTypeUnknown; + + Path = PathString->Buffer; + Chars = PathString->Length / sizeof(WCHAR); + + /* Return if there are no characters */ + if (!Chars) return RtlPathTypeUnknown; + + /* + * The algorithm is similar to RtlDetermineDosPathNameType_U but here we + * actually check for the path length before touching the characters + */ + if ((Chars < 1) || (IS_PATH_SEPARATOR(Path[0]))) + { + if ((Chars < 2) || !(IS_PATH_SEPARATOR(Path[1]))) return RtlPathTypeRooted; /* \x */ + if ((Chars < 3) || ((Path[2] != L'.') && (Path[2] != L'?'))) return RtlPathTypeUncAbsolute;/* \\x */ + if ((Chars >= 4) && (IS_PATH_SEPARATOR(Path[3]))) return RtlPathTypeLocalDevice; /* \\.\x or \\?\x */ + if (Chars != 3) return RtlPathTypeUncAbsolute; /* \\.x or \\?x */ + return RtlPathTypeRootLocalDevice; /* \\. or \\? */ + } + else + { + if ((Chars < 2) || (!(Path[0]) || (Path[1] != L':'))) return RtlPathTypeRelative; /* x */ + if ((Chars < 3) || (IS_PATH_SEPARATOR(Path[2]))) return RtlPathTypeDriveAbsolute; /* x:\ */ + return RtlPathTypeDriveRelative; /* x: */ + } } +NTSTATUS +NTAPI +RtlpCheckDeviceName(IN PUNICODE_STRING FileName, + IN ULONG Length, + OUT PBOOLEAN NameInvalid) +{ + PWCHAR Buffer; + NTSTATUS Status; -/* - * @implemented - * - */ -ULONG NTAPI -RtlDetermineDosPathNameType_U(PCWSTR Path) + /* Allocate a large enough buffer */ + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FileName->Length); + if (Buffer) + { + /* Assume failure */ + *NameInvalid = TRUE; + + /* Copy the filename */ + RtlCopyMemory(Buffer, FileName->Buffer, FileName->Length); + + /* And add a dot at the end */ + Buffer[Length / sizeof(WCHAR)] = L'.'; + Buffer[(Length / sizeof(WCHAR)) + 1] = UNICODE_NULL; + + /* Check if the file exists or not */ + *NameInvalid = RtlDoesFileExists_U(Buffer) ? FALSE: TRUE; + + /* Get rid of the buffer now */ + Status = RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + } + else + { + /* Assume the name is ok, but fail the call */ + *NameInvalid = FALSE; + Status = STATUS_NO_MEMORY; + } + + /* Return the status */ + return Status; +} + +ULONG +NTAPI +RtlGetFullPathName_Ustr(IN PUNICODE_STRING FileName, + IN ULONG Size, + IN PWSTR Buffer, + OUT PCWSTR *ShortName, + OUT PBOOLEAN InvalidName, + OUT RTL_PATH_TYPE *PathType) { - DPRINT("RtlDetermineDosPathNameType_U %S\n", Path); + PWCHAR FileNameBuffer; + ULONG FileNameLength, FileNameChars, DosLength, DosLengthOffset, FullLength; + WCHAR c; + NTSTATUS Status; + + /* For now, assume the name is valid */ + DPRINT("Filename: %wZ\n", FileName); + DPRINT("Size and buffer: %lx %S\n", Size, Buffer); + if (InvalidName) *InvalidName = FALSE; + + /* Handle initial path type and failure case */ + *PathType = RtlPathTypeUnknown; + if (!(Size) || !(Buffer) || !(FileName) || + !(FileName->Length) || (FileName->Buffer[0] == UNICODE_NULL)) return 0; + + /* Break filename into component parts */ + FileNameBuffer = FileName->Buffer; + FileNameLength = FileName->Length; + FileNameChars = FileNameLength / sizeof(WCHAR); + + /* Kill trailing spaces */ + c = FileNameBuffer[FileNameChars - 1]; + while ((FileNameLength) && (c == L' ')) + { + /* Keep going, ignoring the spaces */ + FileNameLength -= sizeof(WCHAR); + if (FileNameLength) c = FileNameBuffer[FileNameLength / sizeof(WCHAR) - 1]; + } - if (Path == NULL) - { - return RtlPathTypeUnknown; - } + /* Check if anything is left */ + if (!FileNameLength) return 0; - if (IS_PATH_SEPARATOR(Path[0])) - { - if (!IS_PATH_SEPARATOR(Path[1])) return RtlPathTypeRooted; /* \xxx */ - if (Path[2] != L'.') return RtlPathTypeUncAbsolute; /* \\xxx */ - if (IS_PATH_SEPARATOR(Path[3])) return RtlPathTypeLocalDevice; /* \\.\xxx */ - if (Path[3]) return RtlPathTypeUncAbsolute; /* \\.xxxx */ + /* Check if this is a DOS name */ + DosLength = RtlIsDosDeviceName_Ustr(FileName); + DPRINT("DOS length for filename: %lx %wZ\n", DosLength, FileName); + if (DosLength) + { + /* Zero out the short name */ + if (ShortName) *ShortName = NULL; - return RtlPathTypeRootLocalDevice; /* \\. */ - } - else - { - if (!Path[0] || Path[1] != L':') return RtlPathTypeRelative; /* xxx */ - if (IS_PATH_SEPARATOR(Path[2])) return RtlPathTypeDriveAbsolute; /* x:\xxx */ + /* See comment for RtlIsDosDeviceName_Ustr if this is confusing... */ + DosLengthOffset = DosLength >> 16; + DosLength = DosLength & 0xFFFF; - return RtlPathTypeDriveRelative; /* x:xxx */ - } + /* Do we have a DOS length, and does the caller want validity? */ + if ((InvalidName) && (DosLengthOffset)) + { + /* Do the check */ + Status = RtlpCheckDeviceName(FileName, DosLengthOffset, InvalidName); + + /* If the check failed, or the name is invalid, fail here */ + if (!NT_SUCCESS(Status)) return 0; + if (*InvalidName) return 0; + } + + /* Add the size of the device root and check if it fits in the size */ + FullLength = DosLength + DeviceRootString.Length; + if (FullLength < Size) + { + /* Add the device string */ + RtlMoveMemory(Buffer, DeviceRootString.Buffer, DeviceRootString.Length); + + /* Now add the DOS device name */ + RtlMoveMemory((PCHAR)Buffer + DeviceRootString.Length, + (PCHAR)FileNameBuffer + DosLengthOffset, + DosLength); + + /* Null terminate */ + *(PWCHAR)((ULONG_PTR)Buffer + FullLength) = UNICODE_NULL; + return FullLength; + } + + /* Otherwise, there's no space, so return the buffer size needed */ + if ((FullLength + sizeof(UNICODE_NULL)) > UNICODE_STRING_MAX_BYTES) return 0; + return FullLength + sizeof(UNICODE_NULL); + } + + /* This should work well enough for our current needs */ + *PathType = RtlDetermineDosPathNameType_U(FileNameBuffer); + DPRINT("Path type: %lx\n", *PathType); + + /* This is disgusting... but avoids re-writing everything */ + DPRINT("Calling old API with %s and %lx and %S\n", FileNameBuffer, Size, Buffer); + return RtlGetFullPathName_U(FileNameBuffer, Size, Buffer, (PWSTR*)ShortName); } +NTSTATUS +NTAPI +RtlpWin32NTNameToNtPathName_U(IN PUNICODE_STRING DosPath, + OUT PUNICODE_STRING NtPath, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) +{ + ULONG DosLength; + PWSTR NewBuffer, p; + + /* Validate the input */ + if (!DosPath) return STATUS_OBJECT_NAME_INVALID; + + /* Validate the DOS length */ + DosLength = DosPath->Length; + if (DosLength >= UNICODE_STRING_MAX_BYTES) return STATUS_NAME_TOO_LONG; + + /* Make space for the new path */ + NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + DosLength + sizeof(UNICODE_NULL)); + if (!NewBuffer) return STATUS_NO_MEMORY; + + /* Copy the prefix, and then the rest of the DOS path, and NULL-terminate */ + RtlCopyMemory(NewBuffer, RtlpDosDevicesPrefix.Buffer, RtlpDosDevicesPrefix.Length); + RtlCopyMemory((PCHAR)NewBuffer + RtlpDosDevicesPrefix.Length, + DosPath->Buffer + RtlpDosDevicesPrefix.Length / sizeof(WCHAR), + DosPath->Length - RtlpDosDevicesPrefix.Length); + NewBuffer[DosLength / sizeof(WCHAR)] = UNICODE_NULL; + + /* Did the caller send a relative name? */ + if (RelativeName) + { + /* Zero initialize it */ + RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0); + RelativeName->ContainingDirectory = NULL; + RelativeName->CurDirRef = 0; + } -/* returns 0 if name is not valid DOS device name, or DWORD with - * offset in bytes to DOS device name from beginning of buffer in high word - * and size in bytes of DOS device name in low word */ + /* Did the caller request a partial name? */ + if (PartName) + { + /* Loop from the back until we find a path separator */ + p = &NewBuffer[(DosLength - 1) / sizeof (WCHAR)]; + while (p > NewBuffer) if (*p-- == '\\') break; -/* - * @implemented - */ -ULONG NTAPI -RtlIsDosDeviceName_U(PWSTR dos_name) + /* Was one found? */ + if (p > NewBuffer) + { + /* Move past it -- anything left? */ + p++; + if (!*p) + { + /* The path ends with a path separator, no part name */ + *PartName = NULL; + } + else + { + /* What follows the path separator is the part name */ + *PartName = p; + } + } + } + + /* Build the final NT path string */ + NtPath->Length = DosLength; + NtPath->Buffer = NewBuffer; + NtPath->MaximumLength = DosLength + sizeof(UNICODE_NULL); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative, + IN PCUNICODE_STRING DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) { - static const WCHAR consoleW[] = {'\\','\\','.','\\','C','O','N',0}; - static const WCHAR auxW[3] = {'A','U','X'}; - static const WCHAR comW[3] = {'C','O','M'}; - static const WCHAR conW[3] = {'C','O','N'}; - static const WCHAR lptW[3] = {'L','P','T'}; - static const WCHAR nulW[3] = {'N','U','L'}; - static const WCHAR prnW[3] = {'P','R','N'}; + WCHAR BigBuffer[MAX_PATH + 1]; + PWCHAR PrefixBuffer, NewBuffer, Buffer; + ULONG MaxLength, PathLength, PrefixLength, PrefixCut, LengthChars, Length; + UNICODE_STRING CapturedDosName, PartNameString; + BOOLEAN QuickPath; + RTL_PATH_TYPE InputPathType, BufferPathType; + NTSTATUS Status; + BOOLEAN NameInvalid; + + /* Assume MAX_PATH for now */ + DPRINT("Relative: %lx DosName: %wZ NtName: %wZ, PartName: %p, RelativeName: %p\n", + HaveRelative, DosName, NtName, PartName, RelativeName); + MaxLength = sizeof(BigBuffer); + + /* Validate the input */ + if (!DosName) return STATUS_OBJECT_NAME_INVALID; + + /* Capture input string */ + CapturedDosName = *DosName; + + /* Check for \\?\\ form */ + if ((CapturedDosName.Length <= RtlpWin32NtRootSlash.Length) || + (CapturedDosName.Buffer[0] != RtlpWin32NtRootSlash.Buffer[0]) || + (CapturedDosName.Buffer[1] != RtlpWin32NtRootSlash.Buffer[1]) || + (CapturedDosName.Buffer[2] != RtlpWin32NtRootSlash.Buffer[2]) || + (CapturedDosName.Buffer[3] != RtlpWin32NtRootSlash.Buffer[3])) + { + /* Quick path won't be used */ + QuickPath = FALSE; - const WCHAR *start, *end, *p; + /* Use the static buffer */ + Buffer = BigBuffer; + MaxLength += RtlpDosDevicesUncPrefix.Length; - switch(RtlDetermineDosPathNameType_U( dos_name )) + /* Allocate a buffer to hold the path */ + NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MaxLength); + DPRINT("Length: %lx\n", MaxLength); + if (!NewBuffer) return STATUS_NO_MEMORY; + } + else { - case RtlPathTypeUnknown: - case RtlPathTypeUncAbsolute: - return 0; - case RtlPathTypeLocalDevice: - if (!_wcsicmp( dos_name, consoleW )) - return MAKELONG( sizeof(conW), 4 * sizeof(WCHAR) ); /* 4 is length of \\.\ prefix */ - return 0; - case RtlPathTypeDriveAbsolute: - case RtlPathTypeDriveRelative: - start = dos_name + 2; /* skip drive letter */ - break; - default: - start = dos_name; - break; + /* Use the optimized path after acquiring the lock */ + QuickPath = 1; + NewBuffer = NULL; } - /* find start of file name */ - for (p = start; *p; p++) if (IS_PATH_SEPARATOR(*p)) start = p + 1; + /* Lock the PEB and check if the quick path can be used */ + RtlAcquirePebLock(); + if (QuickPath) + { + /* Some simple fixups will get us the correct path */ + DPRINT("Quick path\n"); + Status = RtlpWin32NTNameToNtPathName_U(&CapturedDosName, + NtName, + PartName, + RelativeName); + + /* Release the lock, we're done here */ + RtlReleasePebLock(); + return Status; + } - /* truncate at extension and ':' */ - for (end = start; *end; end++) if (*end == '.' || *end == ':') break; - end--; + /* Call the main function to get the full path name and length */ + PathLength = RtlGetFullPathName_Ustr(&CapturedDosName, + MAX_PATH * sizeof(WCHAR), + Buffer, + PartName, + &NameInvalid, + &InputPathType); + if ((NameInvalid) || !(PathLength) || (PathLength > (MAX_PATH * sizeof(WCHAR)))) + { + /* Invalid name, fail */ + DPRINT("Invalid name: %lx Path Length: %lx\n", NameInvalid, PathLength); + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer); + RtlReleasePebLock(); + return STATUS_OBJECT_NAME_INVALID; + } - /* remove trailing spaces */ - while (end >= start && *end == ' ') end--; + /* Start by assuming the path starts with \??\ (DOS Devices Path) */ + PrefixLength = RtlpDosDevicesPrefix.Length; + PrefixBuffer = RtlpDosDevicesPrefix.Buffer; + PrefixCut = 0; - /* now we have a potential device name between start and end, check it */ - switch(end - start + 1) + /* Check where it really is */ + BufferPathType = RtlDetermineDosPathNameType_U(Buffer); + DPRINT("Buffer: %S Type: %lx\n", Buffer, BufferPathType); + switch (BufferPathType) { - case 3: - if (_wcsnicmp( start, auxW, 3 ) && - _wcsnicmp( start, conW, 3 ) && - _wcsnicmp( start, nulW, 3 ) && - _wcsnicmp( start, prnW, 3 )) break; - return MAKELONG( 3 * sizeof(WCHAR), (start - dos_name) * sizeof(WCHAR) ); - case 4: - if (_wcsnicmp( start, comW, 3 ) && _wcsnicmp( start, lptW, 3 )) break; - if (*end <= '0' || *end > '9') break; - return MAKELONG( 4 * sizeof(WCHAR), (start - dos_name) * sizeof(WCHAR) ); - default: /* can't match anything */ - break; + /* It's actually a UNC path in \??\UNC\ */ + case RtlPathTypeUncAbsolute: + PrefixLength = RtlpDosDevicesUncPrefix.Length; + PrefixBuffer = RtlpDosDevicesUncPrefix.Buffer; + PrefixCut = 2; + break; + + case RtlPathTypeLocalDevice: + /* We made a good guess, go with it but skip the \??\ */ + PrefixCut = 4; + break; + + case RtlPathTypeDriveAbsolute: + case RtlPathTypeDriveRelative: + case RtlPathTypeRooted: + case RtlPathTypeRelative: + /* Our guess was good, roll with it */ + break; + + /* Nothing else is expected */ + default: + ASSERT(FALSE); + } - return 0; + + /* Now copy the prefix and the buffer */ + RtlCopyMemory(NewBuffer, PrefixBuffer, PrefixLength); + RtlCopyMemory((PCHAR)NewBuffer + PrefixLength, + &Buffer[PrefixCut], + PathLength - (PrefixCut * sizeof(WCHAR))); + + /* Compute the length */ + Length = PathLength - PrefixCut * sizeof(WCHAR) + PrefixLength; + LengthChars = Length / sizeof(WCHAR); + + /* Setup the actual NT path string and terminate it */ + NtName->Buffer = NewBuffer; + NtName->Length = Length; + NtName->MaximumLength = MaxLength; + NewBuffer[LengthChars] = UNICODE_NULL; + DPRINT("new buffer: %S\n", NewBuffer); + DPRINT("NT Name: %wZ\n", NtName); + + /* Check if a partial name was requested */ + if ((PartName) && (*PartName)) + { + /* Convert to Unicode */ + Status = RtlInitUnicodeStringEx(&PartNameString, *PartName); + if (NT_SUCCESS(Status)) + { + /* Set the partial name */ + *PartName = &NewBuffer[LengthChars - (PartNameString.Length / sizeof(WCHAR))]; + } + else + { + /* Fail */ + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer); + RtlReleasePebLock(); + return Status; + } + } + + /* Check if a relative name was asked for */ + if (RelativeName) + { + /* Setup the structure */ + RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0); + RelativeName->ContainingDirectory = NULL; + RelativeName->CurDirRef = 0; + + /* Check if the input path itself was relative */ + if (InputPathType == RtlPathTypeRelative) + { + /* FIXME: HACK: Old code */ + PCURDIR cd; + UNICODE_STRING us; + cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath); + if (cd->Handle) + { + RtlInitUnicodeString(&us, Buffer); + us.Length = (cd->DosPath.Length < us.Length) ? cd->DosPath.Length : us.Length; + if (RtlEqualUnicodeString(&us, &cd->DosPath, TRUE)) + { + Length = ((cd->DosPath.Length / sizeof(WCHAR)) - PrefixCut) + ((InputPathType == 1) ? 8 : 4); + RelativeName->RelativeName.Buffer = NewBuffer + Length; + RelativeName->RelativeName.Length = NtName->Length - (Length * sizeof(WCHAR)); + RelativeName->RelativeName.MaximumLength = RelativeName->RelativeName.Length; + RelativeName->ContainingDirectory = cd->Handle; + } + } + } + } + + /* Done */ + RtlReleasePebLock(); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +RtlpDosPathNameToRelativeNtPathName_U(IN BOOLEAN HaveRelative, + IN PCWSTR DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) +{ + NTSTATUS Status; + UNICODE_STRING NameString; + + /* Create the unicode name */ + Status = RtlInitUnicodeStringEx(&NameString, DosName); + if (NT_SUCCESS(Status)) + { + /* Call the unicode function */ + Status = RtlpDosPathNameToRelativeNtPathName_Ustr(HaveRelative, + &NameString, + NtName, + PartName, + RelativeName); + } + + /* Return status */ + return Status; +} + +BOOLEAN +NTAPI +RtlDosPathNameToRelativeNtPathName_Ustr(IN PCUNICODE_STRING DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) +{ + /* Call the internal function */ + ASSERT(RelativeName); + return NT_SUCCESS(RtlpDosPathNameToRelativeNtPathName_Ustr(TRUE, + DosName, + NtName, + PartName, + RelativeName)); +} + +BOOLEAN +NTAPI +RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName, + IN BOOLEAN SucceedIfBusy) +{ + BOOLEAN Result; + RTL_RELATIVE_NAME_U RelativeName; + UNICODE_STRING NtPathName; + PVOID Buffer; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + FILE_BASIC_INFORMATION BasicInformation; + + /* Validate the input */ + if (!FileName) return FALSE; + + /* Get the NT Path */ + Result = RtlDosPathNameToRelativeNtPathName_Ustr(FileName, + &NtPathName, + NULL, + &RelativeName); + if (!Result) return FALSE; + + /* Save the buffer */ + Buffer = NtPathName.Buffer; + + /* Check if we have a relative name */ + if (RelativeName.RelativeName.Length) + { + /* Use it */ + NtPathName = RelativeName.RelativeName; + } + else + { + /* Otherwise ignore it */ + RelativeName.ContainingDirectory = NULL; + } + + /* Initialize the object attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &NtPathName, + OBJ_CASE_INSENSITIVE, + RelativeName.ContainingDirectory, + NULL); + + /* Query the attributes and free the buffer now */ + Status = ZwQueryAttributesFile(&ObjectAttributes, &BasicInformation); + RtlReleaseRelativeName(&RelativeName); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + /* Check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Check if we failed because the file is in use */ + if ((Status == STATUS_SHARING_VIOLATION) || + (Status == STATUS_ACCESS_DENIED)) + { + /* Check if the caller wants this to be considered OK */ + Result = SucceedIfBusy ? TRUE : FALSE; + } + else + { + /* A failure because the file didn't exist */ + Result = FALSE; + } + } + else + { + /* The file exists */ + Result = TRUE; + } + + /* Return the result */ + return Result; } +BOOLEAN +NTAPI +RtlDoesFileExists_UStr(IN PUNICODE_STRING FileName) +{ + /* Call the updated API */ + return RtlDoesFileExists_UstrEx(FileName, TRUE); +} + +BOOLEAN +NTAPI +RtlDoesFileExists_UEx(IN PCWSTR FileName, + IN BOOLEAN SucceedIfBusy) +{ + UNICODE_STRING NameString; + + /* Create the unicode name*/ + if (NT_SUCCESS(RtlInitUnicodeStringEx(&NameString, FileName))) + { + /* Call the unicode function */ + return RtlDoesFileExists_UstrEx(&NameString, SucceedIfBusy); + } + + /* Fail */ + return FALSE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ /* * @implemented */ -ULONG NTAPI -RtlGetCurrentDirectory_U(ULONG MaximumLength, - PWSTR Buffer) +VOID +NTAPI +RtlReleaseRelativeName(IN PRTL_RELATIVE_NAME_U RelativeName) { - ULONG Length; - PCURDIR cd; + /* Check if a directory reference was grabbed */ + if (RelativeName->CurDirRef) + { + /* FIXME: Not yet supported */ + UNIMPLEMENTED; + RelativeName->CurDirRef = NULL; + } +} - DPRINT ("RtlGetCurrentDirectory %lu %p\n", MaximumLength, Buffer); +/* + * @implemented + */ +ULONG +NTAPI +RtlGetLongestNtPathLength(VOID) +{ + /* + * The longest NT path is a DOS path that actually sits on a UNC path (ie: + * a mapped network drive), which is accessed through the DOS Global?? path. + * This is, and has always been equal to, 269 characters, except in Wine + * which claims this is 277. Go figure. + */ + return (MAX_PATH + RtlpDosDevicesUncPrefix.Length + sizeof(ANSI_NULL)); +} - RtlAcquirePebLock(); +/* + * @implemented + */ +ULONG +NTAPI +RtlDetermineDosPathNameType_U(IN PCWSTR Path) +{ + DPRINT("RtlDetermineDosPathNameType_U %S\n", Path); - cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath); - Length = cd->DosPath.Length / sizeof(WCHAR); - if (cd->DosPath.Buffer[Length - 1] == L'\\' && - cd->DosPath.Buffer[Length - 2] != L':') - Length--; + /* Validate the input */ + if (!Path) return RtlPathTypeUnknown; - DPRINT ("cd->DosPath.Buffer %S Length %lu\n", - cd->DosPath.Buffer, Length); + /* Unlike the newer RtlDetermineDosPathNameType_U we assume 4 characters */ + if (IS_PATH_SEPARATOR(Path[0])) + { + if (!IS_PATH_SEPARATOR(Path[1])) return RtlPathTypeRooted; /* \x */ + if ((Path[2] != L'.') && (Path[2] != L'?')) return RtlPathTypeUncAbsolute;/* \\x */ + if (IS_PATH_SEPARATOR(Path[3])) return RtlPathTypeLocalDevice; /* \\.\x or \\?\x */ + if (Path[3]) return RtlPathTypeUncAbsolute; /* \\.x or \\?x */ + return RtlPathTypeRootLocalDevice; /* \\. or \\? */ + } + else + { + if (!(Path[0]) || (Path[1] != L':')) return RtlPathTypeRelative; /* x */ + if (IS_PATH_SEPARATOR(Path[2])) return RtlPathTypeDriveAbsolute; /* x:\ */ + return RtlPathTypeDriveRelative; /* x: */ + } +} - if (MaximumLength / sizeof(WCHAR) > Length) - { - memcpy (Buffer, - cd->DosPath.Buffer, - Length * sizeof(WCHAR)); - Buffer[Length] = 0; - } - else - { - Length++; - } +/* + * @implemented + */ +ULONG +NTAPI +RtlIsDosDeviceName_U(IN PWSTR Path) +{ + UNICODE_STRING PathString; + NTSTATUS Status; + + /* Build the string */ + Status = RtlInitUnicodeStringEx(&PathString, Path); + if (!NT_SUCCESS(Status)) return 0; + + /* + * Returns 0 if name is not valid DOS device name, or DWORD with + * offset in bytes to DOS device name from beginning of buffer in high word + * and size in bytes of DOS device name in low word + */ + return RtlIsDosDeviceName_Ustr(&PathString); +} - RtlReleasePebLock (); +/* + * @implemented + */ +ULONG +NTAPI +RtlGetCurrentDirectory_U(IN ULONG MaximumLength, + IN PWSTR Buffer) +{ + ULONG Length, Bytes; + PCURDIR CurDir; + PWSTR CurDirName; + DPRINT("RtlGetCurrentDirectory %lu %p\n", MaximumLength, Buffer); - DPRINT ("CurrentDirectory %S\n", Buffer); + /* Lock the PEB to get the current directory */ + RtlAcquirePebLock(); + CurDir = &NtCurrentPeb()->ProcessParameters->CurrentDirectory; - return (Length * sizeof(WCHAR)); -} + /* Get the buffer and character length */ + CurDirName = CurDir->DosPath.Buffer; + Length = CurDir->DosPath.Length / sizeof(WCHAR); + ASSERT((CurDirName != NULL) && (Length > 0)); + /* Check for x:\ vs x:\path\foo (note the trailing slash) */ + Bytes = Length * sizeof(WCHAR); + if ((Length <= 1) || (CurDirName[Length - 2] == L':')) + { + /* Check if caller does not have enough space */ + if (MaximumLength <= Bytes) + { + /* Call has no space for it, fail, add the trailing slash */ + RtlReleasePebLock(); + return Bytes + sizeof(L'\\'); + } + } + else + { + /* Check if caller does not have enough space */ + if (MaximumLength <= Bytes) + { + /* Call has no space for it, fail */ + RtlReleasePebLock(); + return Bytes; + } + } + + /* Copy the buffer since we seem to have space */ + RtlCopyMemory(Buffer, CurDirName, Bytes); + + /* The buffer should end with a path separator */ + ASSERT(Buffer[Length - 1] == L'\\'); + + /* Again check for our two cases (drive root vs path) */ + if ((Length <= 1) || (Buffer[Length - 2] != L':')) + { + /* Replace the trailing slash with a null */ + Buffer[Length - 1] = UNICODE_NULL; + --Length; + } + else + { + /* Append the null char since there's no trailing slash */ + Buffer[Length] = UNICODE_NULL; + } + + /* Release PEB lock */ + RtlReleasePebLock(); + DPRINT("CurrentDirectory %S\n", Buffer); + return Length * sizeof(WCHAR); +} /* * @implemented @@ -628,328 +1365,250 @@ ULONG NTAPI RtlGetFullPathName_U( return reqsize; } +/* + * @implemented + */ +BOOLEAN +NTAPI +RtlDosPathNameToNtPathName_U(IN PCWSTR DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) +{ + /* Call the internal function */ + return NT_SUCCESS(RtlpDosPathNameToRelativeNtPathName_U(FALSE, + DosName, + NtName, + PartName, + RelativeName)); +} /* * @implemented */ -BOOLEAN NTAPI -RtlDosPathNameToNtPathName_U(IN PCWSTR DosPathName, - OUT PUNICODE_STRING NtPathName, - OUT PCWSTR *NtFileNamePart, - OUT CURDIR *DirectoryInfo) +NTSTATUS +NTAPI +RtlDosPathNameToNtPathName_U_WithStatus(IN PCWSTR DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) { - UNICODE_STRING us; - PCURDIR cd; - ULONG Type; - ULONG Size; - ULONG Length; - ULONG tmpLength; - ULONG Offset; - WCHAR fullname[MAX_PATH + 1]; - PWSTR Buffer = NULL; - - RtlInitUnicodeString (&us, DosPathName); - if (us.Length > 8) - { - Buffer = us.Buffer; - /* check for "\\?\" - allows to use very long filenames ( up to 32k ) */ - if (Buffer[0] == L'\\' && Buffer[1] == L'\\' && - Buffer[2] == L'?' && Buffer[3] == L'\\') - { - /* allocate the new string and simply copy it */ - NtPathName->Length = us.Length; - NtPathName->MaximumLength = us.Length + sizeof(WCHAR); - NtPathName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - NtPathName->MaximumLength); - if (NtPathName->Buffer == NULL) - { - return FALSE; - } - - /* copy the string */ - RtlCopyMemory(NtPathName->Buffer, - us.Buffer, - NtPathName->Length); - NtPathName->Buffer[us.Length / sizeof(WCHAR)] = L'\0'; - - /* change the \\?\ prefix to \??\ */ - NtPathName->Buffer[1] = L'?'; - - if (NtFileNamePart != NULL) - { - PWSTR FilePart = NULL; - PWSTR s; - - /* try to find the last separator */ - s = NtPathName->Buffer + (NtPathName->Length / sizeof(WCHAR)); - while (s != NtPathName->Buffer) - { - if (*s == L'\\') - { - FilePart = s + 1; - break; - } - s--; - } - - *NtFileNamePart = FilePart; - } - - if (DirectoryInfo != NULL) - { - DirectoryInfo->DosPath.Length = 0; - DirectoryInfo->DosPath.MaximumLength = 0; - DirectoryInfo->DosPath.Buffer = NULL; - DirectoryInfo->Handle = NULL; - } - - return TRUE; - } - } - - Buffer = RtlAllocateHeap (RtlGetProcessHeap (), - 0, - sizeof( fullname ) + MAX_PFX_SIZE); - if (Buffer == NULL) - { - return FALSE; - } - - RtlAcquirePebLock (); - - Size = RtlGetFullPathName_U (DosPathName, - sizeof(fullname), - fullname, - (PWSTR*)NtFileNamePart); - if (Size == 0 || Size > MAX_PATH * sizeof(WCHAR)) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - Buffer); - RtlReleasePebLock (); - return FALSE; - } - - /* Set NT prefix */ - Offset = 0; - memcpy (Buffer, L"\\??\\", 4 * sizeof(WCHAR)); - tmpLength = 4; - - Type = RtlDetermineDosPathNameType_U (fullname); - switch (Type) - { - case 1: - memcpy (Buffer + tmpLength, L"UNC\\", 4 * sizeof(WCHAR)); - tmpLength += 4; - Offset = 2; - break; /* \\xxx */ - - case 6: - Offset = 4; - break; /* \\.\xxx */ - } - Length = wcslen(fullname + Offset); - memcpy (Buffer + tmpLength, fullname + Offset, (Length + 1) * sizeof(WCHAR)); - Length += tmpLength; - if (Type == RtlPathTypeDriveAbsolute || - Type == RtlPathTypeDriveRelative) - { - /* make the drive letter to uppercase */ - Buffer[tmpLength] = towupper(Buffer[tmpLength]); - } - - /* set NT filename */ - NtPathName->Length = Length * sizeof(WCHAR); - NtPathName->MaximumLength = sizeof(fullname) + MAX_PFX_SIZE; - NtPathName->Buffer = Buffer; - - /* set pointer to file part if possible */ - if (NtFileNamePart && *NtFileNamePart) - *NtFileNamePart = Buffer + Length - wcslen (*NtFileNamePart); - - /* Set name and handle structure if possible */ - if (DirectoryInfo) - { - memset (DirectoryInfo, 0, sizeof(CURDIR)); - cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath); - if (Type == 5 && cd->Handle) - { - RtlInitUnicodeString(&us, fullname); - if (RtlEqualUnicodeString(&us, &cd->DosPath, TRUE)) - { - Length = ((cd->DosPath.Length / sizeof(WCHAR)) - Offset) + ((Type == 1) ? 8 : 4); - DirectoryInfo->DosPath.Buffer = Buffer + Length; - DirectoryInfo->DosPath.Length = NtPathName->Length - (Length * sizeof(WCHAR)); - DirectoryInfo->DosPath.MaximumLength = DirectoryInfo->DosPath.Length; - DirectoryInfo->Handle = cd->Handle; - } - } - } - - RtlReleasePebLock(); - return TRUE; + /* Call the internal function */ + return RtlpDosPathNameToRelativeNtPathName_U(FALSE, + DosName, + NtName, + PartName, + RelativeName); } +/* + * @implemented + */ +BOOLEAN +NTAPI +RtlDosPathNameToRelativeNtPathName_U(IN PWSTR DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) +{ + /* Call the internal function */ + ASSERT(RelativeName); + return NT_SUCCESS(RtlpDosPathNameToRelativeNtPathName_U(TRUE, + DosName, + NtName, + PartName, + RelativeName)); +} /* * @implemented */ -/****************************************************************** - * RtlDosSearchPath_U - * - * Searches a file of name 'name' into a ';' separated list of paths - * (stored in paths) - * Doesn't seem to search elsewhere than the paths list - * Stores the result in buffer (file_part will point to the position - * of the file name in the buffer) - * FIXME: - * - how long shall the paths be ??? (MAX_PATH or larger with \\?\ constructs ???) +NTSTATUS +NTAPI +RtlDosPathNameToRelativeNtPathName_U_WithStatus(IN PWSTR DosName, + OUT PUNICODE_STRING NtName, + OUT PCWSTR *PartName, + OUT PRTL_RELATIVE_NAME_U RelativeName) +{ + /* Call the internal function */ + ASSERT(RelativeName); + return RtlpDosPathNameToRelativeNtPathName_U(TRUE, + DosName, + NtName, + PartName, + RelativeName); +} + +/* + * @unimplemented + */ +NTSTATUS NTAPI +RtlNtPathNameToDosPathName(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4) +{ + DPRINT1("RtlNtPathNameToDosPathName: stub\n"); + return STATUS_NOT_IMPLEMENTED; +} + +/* + * @implemented */ ULONG NTAPI -RtlDosSearchPath_U(PCWSTR paths, - PCWSTR search, - PCWSTR ext, - ULONG buffer_size, - PWSTR buffer, - PWSTR* file_part) +RtlDosSearchPath_U(IN PCWSTR Path, + IN PCWSTR FileName, + IN PCWSTR Extension, + IN ULONG Size, + IN PWSTR Buffer, + OUT PWSTR *PartName) { - RTL_PATH_TYPE type = RtlDetermineDosPathNameType_U(search); - ULONG len = 0; + NTSTATUS Status; + ULONG ExtensionLength, Length, FileNameLength, PathLength; + UNICODE_STRING TempString; + PWCHAR NewBuffer, BufferStart; + PCWSTR p; - if (type == RtlPathTypeRelative) - { - ULONG allocated = 0, needed, filelen; - WCHAR *name = NULL; + /* Validate the input */ + if (!(Path) || !(FileName)) return 0; - filelen = 1 /* for \ */ + wcslen(search) + 1 /* \0 */; + /* Check if this is an absolute path */ + if (RtlDetermineDosPathNameType_U(FileName) != RtlPathTypeRelative) + { + /* Check if the file exists */ + if (RtlDoesFileExists_UEx(FileName, TRUE)) + { + /* Get the full name, which does the DOS lookup */ + return RtlGetFullPathName_U(FileName, Size, Buffer, PartName); + } - /* Windows only checks for '.' without worrying about path components */ - if (wcschr( search, '.' )) ext = NULL; - if (ext != NULL) filelen += wcslen(ext); + /* Doesn't exist, so fail */ + return 0; + } - while (*paths) + /* Scan the filename */ + p = FileName; + while (*p) + { + /* Looking for an extension */ + if (*p == '.') { - LPCWSTR ptr; - - for (needed = 0, ptr = paths; *ptr != 0 && *ptr++ != ';'; needed++); - if (needed + filelen > allocated) - { - if (!name) name = RtlAllocateHeap(RtlGetProcessHeap(), 0, - (needed + filelen) * sizeof(WCHAR)); - else - { - WCHAR *newname = RtlReAllocateHeap(RtlGetProcessHeap(), 0, name, - (needed + filelen) * sizeof(WCHAR)); - if (!newname) RtlFreeHeap(RtlGetProcessHeap(), 0, name); - name = newname; - } - if (!name) return 0; - allocated = needed + filelen; - } - memmove(name, paths, needed * sizeof(WCHAR)); - /* append '\\' if none is present */ - if (needed > 0 && name[needed - 1] != '\\') name[needed++] = '\\'; - wcscpy(&name[needed], search); - if (ext) wcscat(&name[needed], ext); - if (RtlDoesFileExists_U(name)) - { - len = RtlGetFullPathName_U(name, buffer_size, buffer, file_part); - break; - } - paths = ptr; + /* No extension string needed -- it's part of the filename */ + Extension = NULL; + break; } - RtlFreeHeap(RtlGetProcessHeap(), 0, name); + + /* Next character */ + p++; } - else if (RtlDoesFileExists_U(search)) + + /* Do we have an extension? */ + if (!Extension) { - len = RtlGetFullPathName_U(search, buffer_size, buffer, file_part); + /* Nope, don't worry about one */ + ExtensionLength = 0; + } + else + { + /* Build a temporary string to get the extension length */ + Status = RtlInitUnicodeStringEx(&TempString, Extension); + if (!NT_SUCCESS(Status)) return 0; + ExtensionLength = TempString.Length; } - return len; -} - - -/* - * @implemented - */ -BOOLEAN NTAPI -RtlDoesFileExists_U(IN PCWSTR FileName) -{ - UNICODE_STRING NtFileName; - OBJECT_ATTRIBUTES Attr; - FILE_BASIC_INFORMATION Info; - NTSTATUS Status; - CURDIR CurDir; - - if (!RtlDosPathNameToNtPathName_U (FileName, - &NtFileName, - NULL, - &CurDir)) - return FALSE; - - if (CurDir.DosPath.Length) - NtFileName = CurDir.DosPath; - else - CurDir.Handle = 0; + /* Build a temporary string to get the path length */ + Status = RtlInitUnicodeStringEx(&TempString, Path); + if (!NT_SUCCESS(Status)) return 0; + PathLength = TempString.Length; + + /* Build a temporary string to get the filename length */ + Status = RtlInitUnicodeStringEx(&TempString, FileName); + if (!NT_SUCCESS(Status)) return 0; + FileNameLength = TempString.Length; + + /* Allocate the buffer for the new string name */ + NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + FileNameLength + + ExtensionLength + + PathLength + + 3 * sizeof(WCHAR)); + if (!NewBuffer) + { + /* Fail the call */ + DbgPrint("%s: Failing due to out of memory (RtlAllocateHeap failure)\n", + __FUNCTION__); + return 0; + } - InitializeObjectAttributes (&Attr, - &NtFileName, - OBJ_CASE_INSENSITIVE, - CurDir.Handle, - NULL); + /* Final loop to build the path */ + while (TRUE) + { + /* Check if we have a valid character */ + BufferStart = NewBuffer; + if (*Path) + { + /* Loop as long as there's no semicolon */ + while (*Path != ';') + { + /* Copy the next character */ + *BufferStart++ = *Path++; + if (!*Path) break; + } - Status = ZwQueryAttributesFile (&Attr, &Info); + /* We found a semi-colon, to stop path processing on this loop */ + if (*Path == ';') ++Path; + } - RtlFreeUnicodeString(&NtFileName); + /* Add a terminating slash if needed */ + if ((BufferStart != NewBuffer) && (BufferStart[-1] != '\\')) + { + *BufferStart++ = '\\'; + } + /* Bail out if we reached the end */ + if (!*Path) Path = NULL; - if (NT_SUCCESS(Status) || - Status == STATUS_SHARING_VIOLATION || - Status == STATUS_ACCESS_DENIED) - return TRUE; + /* Copy the file name and check if an extension is needed */ + RtlCopyMemory(BufferStart, FileName, FileNameLength); + if (ExtensionLength) + { + /* Copy the extension too */ + RtlCopyMemory((PCHAR)BufferStart + FileNameLength, + Extension, + ExtensionLength + sizeof(WCHAR)); + } + else + { + /* Just NULL-terminate */ + *(PWCHAR)((PCHAR)BufferStart + FileNameLength) = UNICODE_NULL; + } - return FALSE; -} + /* Now, does this file exist? */ + if (RtlDoesFileExists_UEx(NewBuffer, FALSE)) + { + /* Call the full-path API to get the length */ + Length = RtlGetFullPathName_U(NewBuffer, Size, Buffer, PartName); + break; + } + /* If we got here, path doesn't exist, so fail the call */ + Length = 0; + if (!Path) break; + } -/* - * @unimplemented - */ -BOOLEAN NTAPI -RtlDosPathNameToRelativeNtPathName_U(PVOID Unknown1, - PVOID Unknown2, - PVOID Unknown3, - PVOID Unknown4) -{ - DPRINT1("RtlDosPathNameToRelativeNtPathName_U(0x%p, 0x%p, 0x%p, 0x%p) UNIMPLEMENTED!\n", - Unknown1, Unknown2, Unknown3, Unknown4); - return FALSE; + /* Free the allocation and return the length */ + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer); + return Length; } - /* - * @unimplemented + * @implemented */ -VOID NTAPI -RtlReleaseRelativeName(PVOID Unknown) -{ - DPRINT1("RtlReleaseRelativeName(0x%p) UNIMPLEMENTED\n", Unknown); -} - -NTSTATUS NTAPI -RtlpEnsureBufferSize(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) -{ - DPRINT1("RtlpEnsureBufferSize: stub\n"); - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS NTAPI -RtlNtPathNameToDosPathName(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4) +BOOLEAN +NTAPI +RtlDoesFileExists_U(IN PCWSTR FileName) { - DPRINT1("RtlNtPathNameToDosPathName: stub\n"); - return STATUS_NOT_IMPLEMENTED; + /* Call the new function */ + return RtlDoesFileExists_UEx(FileName, TRUE); } /* EOF */ diff --git a/lib/rtl/splaytree.c b/lib/rtl/splaytree.c index df319e21e7f..28f1027d175 100644 --- a/lib/rtl/splaytree.c +++ b/lib/rtl/splaytree.c @@ -13,13 +13,134 @@ #define NDEBUG #include +//#define VERIFY_SWAP_SPLAY_LINKS + /* FUNCTIONS ***************************************************************/ +static +VOID +FixupChildLinks(PRTL_SPLAY_LINKS Links, BOOLEAN Root, BOOLEAN LeftChild) +{ + if (RtlLeftChild(Links)) { + RtlInsertAsLeftChild(Links, RtlLeftChild(Links)); + } + if (RtlRightChild(Links)) { + RtlInsertAsRightChild(Links, RtlRightChild(Links)); + } + if (!Root) { + if (LeftChild) { + RtlInsertAsLeftChild(RtlParent(Links), Links); + } else { + RtlInsertAsRightChild(RtlParent(Links), Links); + } + } +} + +/* + +Given the tree: + D + B F +A C E G + +Swap(Q,S): + +Q S Q.P Q.L Q.R S.P S.L S.R +A C S.P S.L S.R Q.P Q.L Q.R +B A S S.L S.R Q.P Q Q.R +B C S S.L S.R Q.P Q.L Q +D A S.P S.L S.R S Q.L Q.R +D B S S.L S.R S Q Q.R +D F S S.L S.R S Q.L Q + +When Q is the immediate parent of S, + Set Q's parent to S, and the proper child ptr of S to Q +When Q is the root, + Set S's parent to S + */ + +static VOID SwapSplayLinks(PRTL_SPLAY_LINKS LinkA, PRTL_SPLAY_LINKS LinkB) { - DPRINT1("UNIMPLEMENTED!\n"); + if (RtlParent(LinkA) == LinkB || RtlIsRoot(LinkB)) { + PRTL_SPLAY_LINKS Tmp = LinkA; + LinkA = LinkB; + LinkB = Tmp; + } + + { + RTL_SPLAY_LINKS Ta = *LinkA, Tb = *LinkB; + BOOLEAN RootA = RtlIsRoot(LinkA), + LeftA = RtlIsLeftChild(LinkA), + LeftB = RtlIsLeftChild(LinkB); + *LinkB = Ta; *LinkA = Tb; + + // A was parent of B is a special case: A->Parent is now B + if (RtlParent(&Tb) == LinkA) { + if (!RootA) { + if (LeftA) { + RtlInsertAsLeftChild(RtlParent(&Ta), LinkB); + } else { + RtlInsertAsRightChild(RtlParent(&Ta), LinkB); + } + } + if (LeftB) { + RtlInsertAsLeftChild(LinkB, LinkA); + } else { + RtlInsertAsRightChild(LinkB, LinkA); + } + } + + FixupChildLinks(LinkA, FALSE, LeftB); + FixupChildLinks(LinkB, RootA, LeftA); + + // A was root is a special case: B->Parent is now B + if (RootA) + RtlParent(LinkB) = LinkB; + +#ifdef VERIFY_SWAP_SPLAY_LINKS + // Verify the distinct cases of node swap + if (RootA) { + if (RtlParent(&Tb) == LinkA) { + // LinkA = D, LinkB = B + // D B S S.L S.R S Q Q.R + ASSERT(RtlParent(LinkA) == LinkB); + ASSERT(RtlLeftChild(LinkA) == RtlLeftChild(&Tb)); + ASSERT(RtlRightChild(LinkA) == RtlRightChild(&Tb)); + ASSERT(RtlParent(LinkB) == LinkB); + ASSERT(RtlLeftChild(LinkB) == (LeftB ? LinkA : RtlLeftChild(&Ta))); + ASSERT(RtlRightChild(LinkB) == (LeftB ? RtlRightChild(&Ta) : LinkA)); + } else { + // LinkA = D, LinkB = A + // D A S.P S.L S.R S Q.L Q.R + ASSERT(RtlParent(LinkA) == RtlParent(&Tb)); + ASSERT(RtlLeftChild(LinkA) == RtlLeftChild(&Tb)); + ASSERT(RtlRightChild(LinkA) == RtlRightChild(&Tb)); + ASSERT(RtlParent(LinkB) == LinkB); + ASSERT(RtlLeftChild(LinkB) == RtlLeftChild(&Ta)); + ASSERT(RtlRightChild(LinkB) == RtlRightChild(&Ta)); + } + } else { + if (RtlParent(&Tb) == LinkA) { + // LinkA = B, LinkB = A + // B A S S.L S.R Q.P Q Q.R + ASSERT(RtlParent(LinkA) == LinkB); + ASSERT(RtlLeftChild(LinkA) == RtlLeftChild(&Tb)); + ASSERT(RtlRightChild(LinkA) == RtlRightChild(&Tb)); + ASSERT(RtlParent(LinkB) == RtlParent(&Ta)); + ASSERT(RtlLeftChild(LinkB) == (LeftB ? LinkA : RtlLeftChild(&Ta))); + ASSERT(RtlRightChild(LinkB) == (LeftB ? RtlRightChild(&Ta) : LinkA)); + } else { + // LinkA = A, LinkB = C + // A C S.P S.L S.R Q.P Q.L Q.R + ASSERT(!memcmp(LinkA, &Tb, sizeof(Tb))); + ASSERT(!memcmp(LinkB, &Ta, sizeof(Ta))); + } + } +#endif + } } /* @@ -513,6 +634,7 @@ RtlSplay(PRTL_SPLAY_LINKS Links) } /* Return the root entry */ + ASSERT(RtlIsRoot(N)); return N; } diff --git a/lib/rtl/unicode.c b/lib/rtl/unicode.c index e49896efa4e..7089bb3697d 100644 --- a/lib/rtl/unicode.c +++ b/lib/rtl/unicode.c @@ -2382,6 +2382,19 @@ RtlValidateUnicodeString(IN ULONG Flags, } } +/* + * @unimplemented + */ +NTSTATUS NTAPI +RtlpEnsureBufferSize(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) +{ + DPRINT1("RtlpEnsureBufferSize: stub\n"); + return STATUS_NOT_IMPLEMENTED; +} + +/* + * @implemented + */ NTSTATUS NTAPI RtlFindCharInUnicodeString(IN ULONG Flags, diff --git a/lib/sdk/crt/crt.cmake b/lib/sdk/crt/crt.cmake index 5f9c01caa39..39bbcb04ad4 100644 --- a/lib/sdk/crt/crt.cmake +++ b/lib/sdk/crt/crt.cmake @@ -45,6 +45,12 @@ list(APPEND CRT_SOURCE math/frexp.c math/huge_val.c math/hypot.c + math/ieee754/j0_y0.c + math/ieee754/j1_y1.c + math/ieee754/jn_yn.c + math/j0_y0.c + math/j1_y1.c + math/jn_yn.c math/ldiv.c math/logf.c math/modf.c diff --git a/lib/sdk/crt/math/ieee754/ieee754.h b/lib/sdk/crt/math/ieee754/ieee754.h new file mode 100644 index 00000000000..888ca20298b --- /dev/null +++ b/lib/sdk/crt/math/ieee754/ieee754.h @@ -0,0 +1,54 @@ +#pragma once + +typedef __int32 int32_t; +typedef unsigned __int32 u_int32_t; + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +static __inline double __ieee754_sqrt(double x) {return sqrt(x);} +static __inline double __ieee754_log(double x) {return log(x);} +static __inline double __cos(double x) {return cos(x);} +static __inline void __sincos(double x, double *s, double *c) +{ + *s = sin(x); + *c = cos(x); +} + +double __ieee754_j0(double); +double __ieee754_j1(double); +double __ieee754_jn(int, double); +double __ieee754_y0(double); +double __ieee754_y1(double); +double __ieee754_yn(int, double); diff --git a/lib/sdk/crt/math/ieee754/j0_y0.c b/lib/sdk/crt/math/ieee754/j0_y0.c new file mode 100644 index 00000000000..e24f85637a7 --- /dev/null +++ b/lib/sdk/crt/math/ieee754/j0_y0.c @@ -0,0 +1,529 @@ +/* @(#)e_j0.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/26, + for performance improvement on pipelined processors. +*/ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_j0.c,v 1.8 1995/05/10 20:45:23 jtc Exp $"; +#endif + +/* __ieee754_j0(x), __ieee754_y0(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j0(x): + * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... + * 2. Reduce x to |x| since j0(x)=j0(-x), and + * for x in (0,2) + * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; + * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) + * for x in (2,inf) + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * as follow: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (cos(x) + sin(x)) + * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j0(nan)= nan + * j0(0) = 1 + * j0(inf) = 0 + * + * Method -- y0(x): + * 1. For x<2. + * Since + * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) + * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. + * We use the following function to approximate y0, + * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 + * where + * U(z) = u00 + u01*z + ... + u06*z^6 + * V(z) = 1 + v01*z + ... + v04*z^4 + * with absolute approximation error bounded by 2**-72. + * Note: For tiny x, U/V = u0 and j0(x)~1, hence + * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) + * 2. For x>=2. + * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * by the method mentioned above. + * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. + */ + +#include "math.h" +#include "ieee754.h" + +#ifdef __STDC__ +static double pzero(double), qzero(double); +#else +static double pzero(), qzero(); +#endif + +#ifdef __STDC__ +static const double +#else +static double +#endif +huge = 1e300, +one = 1.0, +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + /* R0/S0 on [0, 2.00] */ +R[] = {0.0, 0.0, 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ + -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ + 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ + -4.61832688532103189199e-09}, /* 0xBE33D5E7, 0x73D63FCE */ +S[] = {0.0, 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ + 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ + 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ + 1.16614003333790000205e-09}; /* 0x3E1408BC, 0xF4745D8F */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double __ieee754_j0(double x) +#else + double __ieee754_j0(x) + double x; +#endif +{ + double z, s,c,ss,cc,r,u,v,r1,r2,s1,s2,z2,z4; + int32_t hx,ix; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return one/(x*x); + x = fabs(x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + __sincos (x, &s, &c); + ss = s-c; + cc = s+c; + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = -__cos(x+x); + if ((s*c)0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(x); + } + return z; + } + if(ix<0x3f200000) { /* |x| < 2**-13 */ + if(huge+x>one) { /* raise inexact if x != 0 */ + if(ix<0x3e400000) return one; /* |x|<2**-27 */ + else return one - 0.25*x*x; + } + } + z = x*x; +#ifdef DO_NOT_USE_THIS + r = z*(R02+z*(R03+z*(R04+z*R05))); + s = one+z*(S01+z*(S02+z*(S03+z*S04))); +#else + r1 = z*R[2]; z2=z*z; + r2 = R[3]+z*R[4]; z4=z2*z2; + r = r1 + z2*r2 + z4*R[5]; + s1 = one+z*S[1]; + s2 = S[2]+z*S[3]; + s = s1 + z2*s2 + z4*S[4]; +#endif + if(ix < 0x3FF00000) { /* |x| < 1.00 */ + return one + z*(-0.25+(r/s)); + } else { + u = 0.5*x; + return((one+u)*(one-u)+z*(r/s)); + } +} + +#ifdef __STDC__ +static const double +#else +static double +#endif +U[] = {-7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ + 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ + -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ + 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ + -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ + 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ + -3.98205194132103398453e-11}, /* 0xBDC5E43D, 0x693FB3C8 */ +V[] = {1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ + 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ + 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ + 4.41110311332675467403e-10}; /* 0x3DFE5018, 0x3BD6D9EF */ + +#ifdef __STDC__ + double __ieee754_y0(double x) +#else + double __ieee754_y0(x) + double x; +#endif +{ + double z, s,c,ss,cc,u,v,z2,z4,z6,u1,u2,u3,v1,v2; + int32_t hx,ix,lx; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0, y0(0) is -inf. */ + if(ix>=0x7ff00000) return one/(x+x*x); + if((ix|lx)==0) return -HUGE_VAL+x; /* -inf and overflow exception. */ + if(hx<0) return zero/(zero*x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) + * where x0 = x-pi/4 + * Better formula: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) + cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + __sincos (x, &s, &c); + ss = s-c; + cc = s+c; + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = -__cos(x+x); + if ((s*c)0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrt(x); + } + return z; + } + if(ix<=0x3e400000) { /* x < 2**-27 */ + return(U[0] + tpi*__ieee754_log(x)); + } + z = x*x; +#ifdef DO_NOT_USE_THIS + u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); + v = one+z*(v01+z*(v02+z*(v03+z*v04))); +#else + u1 = U[0]+z*U[1]; z2=z*z; + u2 = U[2]+z*U[3]; z4=z2*z2; + u3 = U[4]+z*U[5]; z6=z4*z2; + u = u1 + z2*u2 + z4*u3 + z6*U[6]; + v1 = one+z*V[0]; + v2 = V[1]+z*V[2]; + v = v1 + z2*v2 + z4*V[3]; +#endif + return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x))); +} + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + (R/S) + * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 + * S = 1 + pS0*s^2 + ... + pS4*s^10 + * and + * | pzero(x)-1-R/S | <= 2 ** ( -60.26) + */ +#ifdef __STDC__ +static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ + -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ + -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ + -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ + -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ +}; +#ifdef __STDC__ +static const double pS8[5] = { +#else +static double pS8[5] = { +#endif + 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ + 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ + 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ + 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ + 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ +}; + +#ifdef __STDC__ +static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ + -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ + -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ + -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ + -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ + -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ +}; +#ifdef __STDC__ +static const double pS5[5] = { +#else +static double pS5[5] = { +#endif + 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ + 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ + 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ + 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ + 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ +}; + +#ifdef __STDC__ +static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#else +static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ + -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ + -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ + -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ + -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ + -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ +}; +#ifdef __STDC__ +static const double pS3[5] = { +#else +static double pS3[5] = { +#endif + 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ + 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ + 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ + 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ + 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ +}; + +#ifdef __STDC__ +static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ + -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ + -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ + -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ + -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ + -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ +}; +#ifdef __STDC__ +static const double pS2[5] = { +#else +static double pS2[5] = { +#endif + 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ + 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ + 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ + 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ + 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ +}; + +#ifdef __STDC__ + static double pzero(double x) +#else + static double pzero(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p = 0,*q = 0; +#else + double *p = 0,*q = 0; +#endif + double z,r,s,z2,z4,r1,r2,r3,s1,s2,s3; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = pR8; q= pS8;} + else if(ix>=0x40122E8B){p = pR5; q= pS5;} + else if(ix>=0x4006DB6D){p = pR3; q= pS3;} + else if(ix>=0x40000000){p = pR2; q= pS2;} + z = one/(x*x); +#ifdef DO_NOT_USE_THIS + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); +#else + r1 = p[0]+z*p[1]; z2=z*z; + r2 = p[2]+z*p[3]; z4=z2*z2; + r3 = p[4]+z*p[5]; + r = r1 + z2*r2 + z4*r3; + s1 = one+z*q[0]; + s2 = q[1]+z*q[2]; + s3 = q[3]+z*q[4]; + s = s1 + z2*s2 + z4*s3; +#endif + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate pzero by + * qzero(x) = s*(-1.25 + (R/S)) + * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 + * S = 1 + qS0*s^2 + ... + qS5*s^12 + * and + * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +#ifdef __STDC__ +static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ + 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ + 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ + 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ + 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ +}; +#ifdef __STDC__ +static const double qS8[6] = { +#else +static double qS8[6] = { +#endif + 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ + 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ + 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ + 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ + 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ + -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ +}; + +#ifdef __STDC__ +static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ + 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ + 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ + 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ + 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ + 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ +}; +#ifdef __STDC__ +static const double qS5[6] = { +#else +static double qS5[6] = { +#endif + 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ + 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ + 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ + 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ + 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ + -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ +}; + +#ifdef __STDC__ +static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#else +static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ + 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ + 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ + 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ + 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ + 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ +}; +#ifdef __STDC__ +static const double qS3[6] = { +#else +static double qS3[6] = { +#endif + 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ + 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ + 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ + 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ + 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ + -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ +}; + +#ifdef __STDC__ +static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ + 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ + 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ + 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ + 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ + 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ +}; +#ifdef __STDC__ +static const double qS2[6] = { +#else +static double qS2[6] = { +#endif + 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ + 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ + 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ + 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ + 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ + -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ +}; + +#ifdef __STDC__ + static double qzero(double x) +#else + static double qzero(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p = 0,*q = 0; +#else + double *p = 0,*q = 0; +#endif + double s,r,z,z2,z4,z6,r1,r2,r3,s1,s2,s3; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = qR8; q= qS8;} + else if(ix>=0x40122E8B){p = qR5; q= qS5;} + else if(ix>=0x4006DB6D){p = qR3; q= qS3;} + else if(ix>=0x40000000){p = qR2; q= qS2;} + z = one/(x*x); +#ifdef DO_NOT_USE_THIS + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); +#else + r1 = p[0]+z*p[1]; z2=z*z; + r2 = p[2]+z*p[3]; z4=z2*z2; + r3 = p[4]+z*p[5]; z6=z4*z2; + r= r1 + z2*r2 + z4*r3; + s1 = one+z*q[0]; + s2 = q[1]+z*q[2]; + s3 = q[3]+z*q[4]; + s = s1 + z2*s2 + z4*s3 +z6*q[5]; +#endif + return (-.125 + r/s)/x; +} diff --git a/lib/sdk/crt/math/ieee754/j1_y1.c b/lib/sdk/crt/math/ieee754/j1_y1.c new file mode 100644 index 00000000000..18c7e6df9b9 --- /dev/null +++ b/lib/sdk/crt/math/ieee754/j1_y1.c @@ -0,0 +1,530 @@ +/* @(#)e_j1.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/26, + for performance improvement on pipelined processors. +*/ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_j1.c,v 1.8 1995/05/10 20:45:27 jtc Exp $"; +#endif + +/* __ieee754_j1(x), __ieee754_y1(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j1(x): + * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... + * 2. Reduce x to |x| since j1(x)=-j1(-x), and + * for x in (0,2) + * j1(x) = x/2 + x*z*R0/S0, where z = x*x; + * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) + * for x in (2,inf) + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * as follow: + * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (sin(x) + cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j1(nan)= nan + * j1(0) = 0 + * j1(inf) = 0 + * + * Method -- y1(x): + * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN + * 2. For x<2. + * Since + * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) + * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. + * We use the following function to approximate y1, + * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 + * where for x in [0,2] (abs err less than 2**-65.89) + * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 + * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 + * Note: For tiny x, 1/x dominate y1 and hence + * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) + * 3. For x>=2. + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * by method mentioned above. + */ + +#include "math.h" +#include "ieee754.h" + +#ifdef __STDC__ +static double pone(double), qone(double); +#else +static double pone(), qone(); +#endif + +#ifdef __STDC__ +static const double +#else +static double +#endif +huge = 1e300, +one = 1.0, +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + /* R0/S0 on [0,2] */ +R[] = {-6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ + 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ + -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ + 4.96727999609584448412e-08}, /* 0x3E6AAAFA, 0x46CA0BD9 */ +S[] = {0.0, 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ + 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ + 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ + 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ + 1.23542274426137913908e-11}; /* 0x3DAB2ACF, 0xCFB97ED8 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double __ieee754_j1(double x) +#else + double __ieee754_j1(x) + double x; +#endif +{ + double z, s,c,ss,cc,r,u,v,y,r1,r2,s1,s2,s3,z2,z4; + int32_t hx,ix; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return one/x; + y = fabs(x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + __sincos (y, &s, &c); + ss = -s-c; + cc = s-c; + if(ix<0x7fe00000) { /* make sure y+y not overflow */ + z = __cos(y+y); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* + * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) + * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) + */ + if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(y); + else { + u = pone(y); v = qone(y); + z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(y); + } + if(hx<0) return -z; + else return z; + } + if(ix<0x3e400000) { /* |x|<2**-27 */ + if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */ + } + z = x*x; +#ifdef DO_NOT_USE_THIS + r = z*(r00+z*(r01+z*(r02+z*r03))); + s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); + r *= x; +#else + r1 = z*R[0]; z2=z*z; + r2 = R[1]+z*R[2]; z4=z2*z2; + r = r1 + z2*r2 + z4*R[3]; + r *= x; + s1 = one+z*S[1]; + s2 = S[2]+z*S[3]; + s3 = S[4]+z*S[5]; + s = s1 + z2*s2 + z4*s3; +#endif + return(x*0.5+r/s); +} + +#ifdef __STDC__ +static const double U0[5] = { +#else +static double U0[5] = { +#endif + -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ + 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ + -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ + 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ + -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ +}; +#ifdef __STDC__ +static const double V0[5] = { +#else +static double V0[5] = { +#endif + 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ + 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ + 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ + 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ + 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ +}; + +#ifdef __STDC__ + double __ieee754_y1(double x) +#else + double __ieee754_y1(x) + double x; +#endif +{ + double z, s,c,ss,cc,u,v,u1,u2,v1,v2,v3,z2,z4; + int32_t hx,ix,lx; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ + if(ix>=0x7ff00000) return one/(x+x*x); + if((ix|lx)==0) return -HUGE_VAL+x; /* -inf and overflow exception. */; + if(hx<0) return zero/(zero*x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + __sincos (x, &s, &c); + ss = -s-c; + cc = s-c; + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = __cos(x+x); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) + * where x0 = x-3pi/4 + * Better formula: + * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (cos(x) + sin(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrt(x); + else { + u = pone(x); v = qone(x); + z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrt(x); + } + return z; + } + if(ix<=0x3c900000) { /* x < 2**-54 */ + return(-tpi/x); + } + z = x*x; +#ifdef DO_NOT_USE_THIS + u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); + v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); +#else + u1 = U0[0]+z*U0[1];z2=z*z; + u2 = U0[2]+z*U0[3];z4=z2*z2; + u = u1 + z2*u2 + z4*U0[4]; + v1 = one+z*V0[0]; + v2 = V0[1]+z*V0[2]; + v3 = V0[3]+z*V0[4]; + v = v1 + z2*v2 + z4*v3; +#endif + return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x)); +} + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pone(x)-1-R/S | <= 2 ** ( -60.06) + */ + +#ifdef __STDC__ +static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ + 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ + 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ + 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ + 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ +}; +#ifdef __STDC__ +static const double ps8[5] = { +#else +static double ps8[5] = { +#endif + 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ + 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ + 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ + 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ + 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ +}; + +#ifdef __STDC__ +static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ + 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ + 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ + 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ + 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ + 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ +}; +#ifdef __STDC__ +static const double ps5[5] = { +#else +static double ps5[5] = { +#endif + 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ + 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ + 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ + 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ + 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ +}; + +#ifdef __STDC__ +static const double pr3[6] = { +#else +static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ + 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ + 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ + 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ + 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ + 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ +}; +#ifdef __STDC__ +static const double ps3[5] = { +#else +static double ps3[5] = { +#endif + 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ + 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ + 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ + 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ + 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ +}; + +#ifdef __STDC__ +static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ + 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ + 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ + 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ + 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ + 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ +}; +#ifdef __STDC__ +static const double ps2[5] = { +#else +static double ps2[5] = { +#endif + 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ + 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ + 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ + 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ + 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ +}; + +#ifdef __STDC__ + static double pone(double x) +#else + static double pone(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p = 0,*q = 0; +#else + double *p = 0,*q = 0; +#endif + double z,r,s,r1,r2,r3,s1,s2,s3,z2,z4; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = pr8; q= ps8;} + else if(ix>=0x40122E8B){p = pr5; q= ps5;} + else if(ix>=0x4006DB6D){p = pr3; q= ps3;} + else if(ix>=0x40000000){p = pr2; q= ps2;} + z = one/(x*x); +#ifdef DO_NOT_USE_THIS + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); +#else + r1 = p[0]+z*p[1]; z2=z*z; + r2 = p[2]+z*p[3]; z4=z2*z2; + r3 = p[4]+z*p[5]; + r = r1 + z2*r2 + z4*r3; + s1 = one+z*q[0]; + s2 = q[1]+z*q[2]; + s3 = q[3]+z*q[4]; + s = s1 + z2*s2 + z4*s3; +#endif + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs1*s^2 + ... + qs6*s^12 + * and + * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +#ifdef __STDC__ +static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ + -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ + -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ + -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ + -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ +}; +#ifdef __STDC__ +static const double qs8[6] = { +#else +static double qs8[6] = { +#endif + 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ + 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ + 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ + 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ + 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ + -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ +}; + +#ifdef __STDC__ +static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ + -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ + -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ + -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ + -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ + -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ +}; +#ifdef __STDC__ +static const double qs5[6] = { +#else +static double qs5[6] = { +#endif + 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ + 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ + 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ + 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ + 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ + -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ +}; + +#ifdef __STDC__ +static const double qr3[6] = { +#else +static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ + -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ + -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ + -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ + -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ + -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ +}; +#ifdef __STDC__ +static const double qs3[6] = { +#else +static double qs3[6] = { +#endif + 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ + 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ + 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ + 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ + 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ + -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ +}; + +#ifdef __STDC__ +static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ + -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ + -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ + -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ + -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ + -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ +}; +#ifdef __STDC__ +static const double qs2[6] = { +#else +static double qs2[6] = { +#endif + 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ + 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ + 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ + 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ + 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ + -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ +}; + +#ifdef __STDC__ + static double qone(double x) +#else + static double qone(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p = 0,*q = 0; +#else + double *p = 0,*q = 0; +#endif + double s,r,z,r1,r2,r3,s1,s2,s3,z2,z4,z6; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = qr8; q= qs8;} + else if(ix>=0x40122E8B){p = qr5; q= qs5;} + else if(ix>=0x4006DB6D){p = qr3; q= qs3;} + else if(ix>=0x40000000){p = qr2; q= qs2;} + z = one/(x*x); +#ifdef DO_NOT_USE_THIS + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); +#else + r1 = p[0]+z*p[1]; z2=z*z; + r2 = p[2]+z*p[3]; z4=z2*z2; + r3 = p[4]+z*p[5]; z6=z4*z2; + r = r1 + z2*r2 + z4*r3; + s1 = one+z*q[0]; + s2 = q[1]+z*q[2]; + s3 = q[3]+z*q[4]; + s = s1 + z2*s2 + z4*s3 + z6*q[5]; +#endif + return (.375 + r/s)/x; +} diff --git a/lib/sdk/crt/math/ieee754/jn_yn.c b/lib/sdk/crt/math/ieee754/jn_yn.c new file mode 100644 index 00000000000..c827b528d25 --- /dev/null +++ b/lib/sdk/crt/math/ieee754/jn_yn.c @@ -0,0 +1,287 @@ +/* @(#)e_jn.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_jn.c,v 1.9 1995/05/10 20:45:34 jtc Exp $"; +#endif + +/* + * __ieee754_jn(n, x), __ieee754_yn(n, x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with overflow signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for nx, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + * + */ + +#include "math.h" +#include "ieee754.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ +one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ + +#ifdef __STDC__ +static const double zero = 0.00000000000000000000e+00; +#else +static double zero = 0.00000000000000000000e+00; +#endif + +#ifdef __STDC__ + double __ieee754_jn(int n, double x) +#else + double __ieee754_jn(n,x) + int n; double x; +#endif +{ + int32_t i,hx,ix,lx, sgn; + double a, b, temp, di; + double z, w; + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if J(n,NaN) is NaN */ + if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; + if(n<0){ + n = -n; + x = -x; + hx ^= 0x80000000; + } + if(n==0) return(__ieee754_j0(x)); + if(n==1) return(__ieee754_j1(x)); + sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ + x = fabs(x); + if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ + b = zero; + else if((double)n<=x) { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if(ix>=0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + double s; + double c; + __sincos (x, &s, &c); + switch(n&3) { + case 0: temp = c + s; break; + case 1: temp = -c + s; break; + case 2: temp = -c - s; break; + case 3: temp = c - s; break; + } + b = invsqrtpi*temp/__ieee754_sqrt(x); + } else { + a = __ieee754_j0(x); + b = __ieee754_j1(x); + for(i=1;i33) /* underflow */ + b = zero; + else { + temp = x*0.5; b = temp; + for (a=one,i=2;i<=n;i++) { + a *= (double)i; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + } + b = b/a; + } + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + double t,v; + double q0,q1,h,tmp; int32_t k,m; + w = (n+n)/(double)x; h = 2.0/(double)x; + q0 = w; z = w+h; q1 = w*z - 1.0; k=1; + while(q1<1.0e9) { + k += 1; z += h; + tmp = z*q1 - q0; + q0 = q1; + q1 = tmp; + } + m = n+n; + for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); + a = t; + b = one; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = n; + v = two/x; + tmp = tmp*__ieee754_log(fabs(v*tmp)); + if(tmp<7.09782712893383973096e+02) { + for(i=n-1,di=(double)(i+i);i>0;i--){ + temp = b; + b *= di; + b = b/x - a; + a = temp; + di -= two; + } + } else { + for(i=n-1,di=(double)(i+i);i>0;i--){ + temp = b; + b *= di; + b = b/x - a; + a = temp; + di -= two; + /* scale b to avoid spurious overflow */ + if(b>1e100) { + a /= b; + t /= b; + b = one; + } + } + } + b = (t*__ieee754_j0(x)/b); + } + } + if(sgn==1) return -b; else return b; +} + +#ifdef __STDC__ + double __ieee754_yn(int n, double x) +#else + double __ieee754_yn(n,x) + int n; double x; +#endif +{ + int32_t i,hx,ix,lx; + int32_t sign; + double a, b, temp; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if Y(n,NaN) is NaN */ + if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; + if((ix|lx)==0) return -HUGE_VAL+x; /* -inf and overflow exception. */; + if(hx<0) return zero/(zero*x); + sign = 1; + if(n<0){ + n = -n; + sign = 1 - ((n&1)<<1); + } + if(n==0) return(__ieee754_y0(x)); + if(n==1) return(sign*__ieee754_y1(x)); + if(ix==0x7ff00000) return zero; + if(ix>=0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + double c; + double s; + __sincos (x, &s, &c); + switch(n&3) { + case 0: temp = s - c; break; + case 1: temp = -s - c; break; + case 2: temp = -s + c; break; + case 3: temp = s + c; break; + } + b = invsqrtpi*temp/__ieee754_sqrt(x); + } else { + u_int32_t high; + a = __ieee754_y0(x); + b = __ieee754_y1(x); + /* quit if b is -inf */ + GET_HIGH_WORD(high,b); + for(i=1;i0) return b; else return -b; +} diff --git a/lib/sdk/crt/math/j0_y0.c b/lib/sdk/crt/math/j0_y0.c index d6787deeb28..c656e210b33 100644 --- a/lib/sdk/crt/math/j0_y0.c +++ b/lib/sdk/crt/math/j0_y0.c @@ -1,4 +1,6 @@ #include +#include +#include "ieee754/ieee754.h" typedef int fpclass_t; fpclass_t _fpclass(double __d); @@ -10,7 +12,7 @@ int *_errno(void); double _j0(double num) { /* FIXME: errno handling */ - return j0(num); + return __ieee754_j0(num); } /* @@ -19,8 +21,8 @@ double _j0(double num) double _y0(double num) { double retval; - if (!isfinite(num)) *_errno() = EDOM; - retval = y0(num); + if (!_finite(num)) *_errno() = EDOM; + retval = __ieee754_y0(num); if (_fpclass(retval) == _FPCLASS_NINF) { *_errno() = EDOM; diff --git a/lib/sdk/crt/math/j1_y1.c b/lib/sdk/crt/math/j1_y1.c index b050889d7ae..7a2bc2a8645 100644 --- a/lib/sdk/crt/math/j1_y1.c +++ b/lib/sdk/crt/math/j1_y1.c @@ -1,4 +1,6 @@ #include +#include +#include "ieee754/ieee754.h" typedef int fpclass_t; fpclass_t _fpclass(double __d); @@ -10,7 +12,7 @@ int *_errno(void); double _j1(double num) { /* FIXME: errno handling */ - return j1(num); + return __ieee754_j1(num); } /* @@ -19,8 +21,8 @@ double _j1(double num) double _y1(double num) { double retval; - if (!isfinite(num)) *_errno() = EDOM; - retval = y1(num); + if (!_finite(num)) *_errno() = EDOM; + retval = __ieee754_y1(num); if (_fpclass(retval) == _FPCLASS_NINF) { *_errno() = EDOM; diff --git a/lib/sdk/crt/math/jn_yn.c b/lib/sdk/crt/math/jn_yn.c index 34f2dee7a4d..141e4f2e951 100644 --- a/lib/sdk/crt/math/jn_yn.c +++ b/lib/sdk/crt/math/jn_yn.c @@ -1,4 +1,6 @@ #include +#include +#include "ieee754/ieee754.h" typedef int fpclass_t; fpclass_t _fpclass(double __d); @@ -10,7 +12,7 @@ int *_errno(void); double _jn(int n, double num) { /* FIXME: errno handling */ - return jn(n, num); + return __ieee754_jn(n, num); } /* @@ -19,8 +21,8 @@ double _jn(int n, double num) double _yn(int order, double num) { double retval; - if (!isfinite(num)) *_errno() = EDOM; - retval = yn(order,num); + if (!_finite(num)) *_errno() = EDOM; + retval = __ieee754_yn(order,num); if (_fpclass(retval) == _FPCLASS_NINF) { *_errno() = EDOM; diff --git a/lib/smlib/CMakeLists.txt b/lib/smlib/CMakeLists.txt index ca5c16de4cd..2bcda9d48c8 100644 --- a/lib/smlib/CMakeLists.txt +++ b/lib/smlib/CMakeLists.txt @@ -8,4 +8,5 @@ list(APPEND SOURCE lookupss.c) add_library(smlib ${SOURCE}) +add_pch(smlib precomp.h) add_dependencies(smlib psdk) diff --git a/ntoskrnl/CMakeLists.txt b/ntoskrnl/CMakeLists.txt index 2640133433b..f970b480d41 100644 --- a/ntoskrnl/CMakeLists.txt +++ b/ntoskrnl/CMakeLists.txt @@ -83,12 +83,12 @@ list(APPEND SOURCE ex/event.c ex/evtpair.c ex/exintrin.c - ex/fastinterlck.c ex/fmutex.c ex/handle.c ex/harderr.c ex/hdlsterm.c ex/init.c + ex/interlocked.c ex/keyedevt.c ex/locale.c ex/lookas.c @@ -276,7 +276,6 @@ list(APPEND SOURCE if(ARCH MATCHES i386) list(APPEND SOURCE config/i386/cmhardwr.c - ex/i386/interlck_asm.S ex/i386/fastinterlck_asm.S ex/i386/ioport.S ke/i386/abios.c @@ -305,7 +304,6 @@ if(ARCH MATCHES i386) elseif(ARCH MATCHES amd64) list(APPEND SOURCE config/i386/cmhardwr.c - ex/amd64/fastinterlck.c ke/amd64/boot.S ke/amd64/context.c ke/amd64/cpu.c diff --git a/ntoskrnl/cache/section/data.c b/ntoskrnl/cache/section/data.c index bfa58827d6c..f168d62b835 100644 --- a/ntoskrnl/cache/section/data.c +++ b/ntoskrnl/cache/section/data.c @@ -58,7 +58,6 @@ extern KSPIN_LOCK MiSectionPageTableLock; /* GLOBALS *******************************************************************/ ULONG_PTR MmSubsectionBase; -BOOLEAN MmAllocationFragment; NTSTATUS NTAPI diff --git a/ntoskrnl/ex/amd64/fastinterlck.c b/ntoskrnl/ex/amd64/fastinterlck.c deleted file mode 100644 index b9ca32aab1b..00000000000 --- a/ntoskrnl/ex/amd64/fastinterlck.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: BSD - See COPYING.ARM in the top level directory - * FILE: ntoskrnl/ex/fastinterlck.c - * PURPOSE: Portable Ex*Interlocked and REGISTER routines for amd64 - * PROGRAMMERS: ReactOS Portable Systems Group - * Timo Kreuzer - */ - -/* INCLUDES *******************************************************************/ - -#include -#define NDEBUG -#include - -#undef ExInterlockedAddLargeInteger -#undef ExInterlockedAddUlong -#undef ExInterlockedExtendZone -#undef ExInterlockedInsertHeadList -#undef ExInterlockedInsertTailList -#undef ExInterlockedPopEntryList -#undef ExInterlockedPushEntryList -#undef ExInterlockedRemoveHeadList -#undef ExpInterlockedFlushSList -#undef ExpInterlockedPopEntrySList -#undef ExpInterlockedPushEntrySList - -/* FUNCTIONS ******************************************************************/ - -LARGE_INTEGER -ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend, - IN LARGE_INTEGER Increment, - IN PKSPIN_LOCK Lock) -{ - LARGE_INTEGER Int; - Int.QuadPart = _InterlockedExchangeAdd64(&Addend->QuadPart, - Increment.QuadPart); - return Int; -} - -ULONG -ExInterlockedAddUlong(IN PULONG Addend, - IN ULONG Increment, - PKSPIN_LOCK Lock) -{ - return (ULONG)_InterlockedExchangeAdd((PLONG)Addend, Increment); -} - -PLIST_ENTRY -ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, - IN PLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = ListEntry->Flink; - InsertHeadList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PLIST_ENTRY -ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead, - IN PLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = ListEntry->Blink; - InsertTailList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PSINGLE_LIST_ENTRY -ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PSINGLE_LIST_ENTRY FirstEntry; - KeAcquireSpinLock(Lock, &OldIrql); - FirstEntry = PopEntryList(ListHead); - KeReleaseSpinLock(Lock, OldIrql); - return FirstEntry; -} - -PSINGLE_LIST_ENTRY -ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - IN PSINGLE_LIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PSINGLE_LIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - OldHead = ListHead->Next; - PushEntryList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PLIST_ENTRY -ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = RemoveHeadList(ListHead); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - diff --git a/ntoskrnl/ex/fastinterlck.c b/ntoskrnl/ex/fastinterlck.c deleted file mode 100644 index d16968a0ea0..00000000000 --- a/ntoskrnl/ex/fastinterlck.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: BSD - See COPYING.ARM in the top level directory - * FILE: ntoskrnl/ex/fastinterlck.c - * PURPOSE: Portable Ex*Interlocked and REGISTER routines for non-x86 - * PROGRAMMERS: ReactOS Portable Systems Group - */ - -/* INCLUDES *******************************************************************/ - -#if defined(_ARM_) || defined(_PPC_) || defined(NTOS_USE_GENERICS) - -#include -#define NDEBUG -#include - -#undef ExInterlockedPushEntrySList -#undef ExInterlockedPopEntrySList -#undef ExInterlockedAddULong -#undef ExInterlockedIncrementLong -#undef ExInterlockedDecrementLong -#undef ExInterlockedAddLargeStatistic - -/* FUNCTIONS ******************************************************************/ - -PSLIST_ENTRY -NTAPI -InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, - IN PSLIST_ENTRY ListEntry) -{ - - PSINGLE_LIST_ENTRY FirstEntry, NextEntry; - PSINGLE_LIST_ENTRY Entry = (PVOID)ListEntry, Head = (PVOID)ListHead; - - FirstEntry = Head->Next; - do - { - Entry->Next = FirstEntry; - NextEntry = FirstEntry; - FirstEntry = (PVOID)_InterlockedCompareExchange((PLONG)Head, - (LONG)Entry, - (LONG)FirstEntry); - } while (FirstEntry != NextEntry); - - return FirstEntry; -} - -PSLIST_ENTRY -NTAPI -InterlockedPopEntrySList(IN PSLIST_HEADER ListHead) -{ - PSINGLE_LIST_ENTRY FirstEntry, NextEntry, Head = (PVOID)ListHead; - - FirstEntry = Head->Next; - do - { - if (!FirstEntry) return NULL; - - NextEntry = FirstEntry; - FirstEntry = (PVOID)_InterlockedCompareExchange((PLONG)Head, - (LONG)FirstEntry->Next, - (LONG)FirstEntry); - } while (FirstEntry != NextEntry); - - return FirstEntry; -} - -PSINGLE_LIST_ENTRY -FASTCALL -ExInterlockedFlushSList(IN PSLIST_HEADER ListHead) -{ - return (PVOID)_InterlockedExchange((PLONG)&ListHead->Next.Next, (LONG)NULL); -} - -PSLIST_ENTRY -FASTCALL -ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead, - IN PSLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - return InterlockedPushEntrySList(ListHead, ListEntry); -} - -PSINGLE_LIST_ENTRY -NTAPI -ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead, - IN PKSPIN_LOCK Lock) -{ - return InterlockedPopEntrySList(ListHead); -} - -ULONG -FASTCALL -ExfInterlockedAddUlong(IN PULONG Addend, - IN ULONG Increment, - PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - KeAcquireSpinLock(Lock, &OldIrql); - *Addend += Increment; - KeReleaseSpinLock(Lock, OldIrql); - return *Addend; -} - -LONGLONG -FASTCALL -ExfInterlockedCompareExchange64(IN OUT LONGLONG volatile *Destination, - IN PLONGLONG Exchange, - IN PLONGLONG Comparand) -{ - LONGLONG Result; - - Result = *Destination; - if (*Destination == *Comparand) *Destination = *Exchange; - return Result; -} - -PLIST_ENTRY -FASTCALL -ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, - IN PLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = ListEntry->Flink; - InsertHeadList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PLIST_ENTRY -FASTCALL -ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead, - IN PLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = ListEntry->Blink; - InsertTailList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PSINGLE_LIST_ENTRY -FASTCALL -ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, - IN PKSPIN_LOCK Lock) -{ - UNIMPLEMENTED; - return NULL; -} - -PSINGLE_LIST_ENTRY -FASTCALL -ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - IN PSINGLE_LIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - UNIMPLEMENTED; - return NULL; -} - -PLIST_ENTRY -FASTCALL -ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead, - IN PKSPIN_LOCK Lock) -{ - return ExInterlockedRemoveHeadList(ListHead, Lock); -} - -LARGE_INTEGER -NTAPI -ExInterlockedAddLargeInteger(IN PLARGE_INTEGER Addend, - IN LARGE_INTEGER Increment, - IN PKSPIN_LOCK Lock) -{ - LARGE_INTEGER Integer = {{0}}; - UNIMPLEMENTED; - return Integer; -} - -ULONG -NTAPI -ExInterlockedAddUlong(IN PULONG Addend, - IN ULONG Increment, - PKSPIN_LOCK Lock) -{ - return (ULONG)_InterlockedExchangeAdd((PLONG)Addend, Increment); -} - -INTERLOCKED_RESULT -NTAPI -ExInterlockedIncrementLong(IN PLONG Addend, - IN PKSPIN_LOCK Lock) -{ - return _InterlockedIncrement(Addend); -} - -INTERLOCKED_RESULT -NTAPI -ExInterlockedDecrementLong(IN PLONG Addend, - IN PKSPIN_LOCK Lock) -{ - return _InterlockedDecrement(Addend); -} - -ULONG -NTAPI -ExInterlockedExchangeUlong(IN PULONG Target, - IN ULONG Value, - IN PKSPIN_LOCK Lock) -{ - return (ULONG)_InterlockedExchange((PLONG)Target, Value); -} - -PLIST_ENTRY -NTAPI -ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, - IN PLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = ListEntry->Flink; - InsertHeadList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PLIST_ENTRY -NTAPI -ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead, - IN PLIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = ListEntry->Blink; - InsertTailList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PSINGLE_LIST_ENTRY -NTAPI -ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PSINGLE_LIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - OldHead = PopEntryList(ListHead); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PSINGLE_LIST_ENTRY -NTAPI -ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - IN PSINGLE_LIST_ENTRY ListEntry, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PSINGLE_LIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - OldHead = ListHead->Next; - PushEntryList(ListHead, ListEntry); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -PLIST_ENTRY -NTAPI -ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - PLIST_ENTRY OldHead = NULL; - KeAcquireSpinLock(Lock, &OldIrql); - if (!IsListEmpty(ListHead)) OldHead = RemoveHeadList(ListHead); - KeReleaseSpinLock(Lock, OldIrql); - return OldHead; -} - -VOID -FASTCALL -ExInterlockedAddLargeStatistic(IN PLONGLONG Addend, - IN ULONG Increment) -{ - UNIMPLEMENTED; -} - -LONGLONG -FASTCALL -ExInterlockedCompareExchange64(IN OUT LONGLONG volatile *Destination, - IN PLONGLONG Exchange, - IN PLONGLONG Comparand, - IN PKSPIN_LOCK Lock) -{ - KIRQL OldIrql; - LONGLONG Result; - - KeAcquireSpinLock(Lock, &OldIrql); - Result = *Destination; - if (*Destination == *Comparand) *Destination = *Exchange; - KeReleaseSpinLock(Lock, OldIrql); - return Result; -} - -VOID -NTAPI -READ_REGISTER_BUFFER_UCHAR(IN PUCHAR Register, - IN PUCHAR Buffer, - IN ULONG Count) -{ - PUCHAR registerBuffer = Register; - PUCHAR readBuffer = Buffer; - ULONG readCount; - - for (readCount = Count; readCount--; readBuffer++, registerBuffer++) - { - *readBuffer = *(volatile UCHAR * const)registerBuffer; - } -} - -VOID -NTAPI -READ_REGISTER_BUFFER_ULONG(IN PULONG Register, - IN PULONG Buffer, - IN ULONG Count) -{ - PULONG registerBuffer = Register; - PULONG readBuffer = Buffer; - ULONG readCount; - - for (readCount = Count; readCount--; readBuffer++, registerBuffer++) - { - *readBuffer = *(volatile ULONG * const)registerBuffer; - } -} - -VOID -NTAPI -READ_REGISTER_BUFFER_USHORT(IN PUSHORT Register, - IN PUSHORT Buffer, - IN ULONG Count) -{ - PUSHORT registerBuffer = Register; - PUSHORT readBuffer = Buffer; - ULONG readCount; - - for (readCount = Count; readCount--; readBuffer++, registerBuffer++) - { - *readBuffer = *(volatile USHORT * const)registerBuffer; - } -} - -UCHAR -NTAPI -READ_REGISTER_UCHAR(IN PUCHAR Register) -{ - return *(volatile UCHAR * const)Register; -} - -ULONG -NTAPI -READ_REGISTER_ULONG(IN PULONG Register) -{ - return *(volatile ULONG * const)Register; -} - -USHORT -NTAPI -READ_REGISTER_USHORT(IN PUSHORT Register) -{ - return *(volatile USHORT * const)Register; -} - -VOID -NTAPI -WRITE_REGISTER_BUFFER_UCHAR(IN PUCHAR Register, - IN PUCHAR Buffer, - IN ULONG Count) -{ - PUCHAR registerBuffer = Register; - PUCHAR writeBuffer = Buffer; - ULONG writeCount; - for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++) - { - *(volatile UCHAR * const)registerBuffer = *writeBuffer; - } - KeFlushWriteBuffer(); -} - -VOID -NTAPI -WRITE_REGISTER_BUFFER_ULONG(IN PULONG Register, - IN PULONG Buffer, - IN ULONG Count) -{ - PULONG registerBuffer = Register; - PULONG writeBuffer = Buffer; - ULONG writeCount; - for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++) - { - *(volatile ULONG * const)registerBuffer = *writeBuffer; - } - KeFlushWriteBuffer(); -} - -VOID -NTAPI -WRITE_REGISTER_BUFFER_USHORT(IN PUSHORT Register, - IN PUSHORT Buffer, - IN ULONG Count) -{ - PUSHORT registerBuffer = Register; - PUSHORT writeBuffer = Buffer; - ULONG writeCount; - for (writeCount = Count; writeCount--; writeBuffer++, registerBuffer++) - { - *(volatile USHORT * const)registerBuffer = *writeBuffer; - } - KeFlushWriteBuffer(); -} - -VOID -NTAPI -WRITE_REGISTER_UCHAR(IN PUCHAR Register, - IN UCHAR Value) -{ - *(volatile UCHAR * const)Register = Value; - KeFlushWriteBuffer(); -} - -VOID -NTAPI -WRITE_REGISTER_ULONG(IN PULONG Register, - IN ULONG Value) -{ - *(volatile ULONG * const)Register = Value; - KeFlushWriteBuffer(); -} - -VOID -NTAPI -WRITE_REGISTER_USHORT(IN PUSHORT Register, - IN USHORT Value) -{ - *(volatile USHORT * const)Register = Value; - KeFlushWriteBuffer(); -} - -#endif diff --git a/ntoskrnl/ex/i386/fastinterlck_asm.S b/ntoskrnl/ex/i386/fastinterlck_asm.S index 566f37f5a0c..8de4260ab87 100644 --- a/ntoskrnl/ex/i386/fastinterlck_asm.S +++ b/ntoskrnl/ex/i386/fastinterlck_asm.S @@ -5,7 +5,7 @@ * PURPOSE: FASTCALL Interlocked Functions * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ - + /* INCLUDES ******************************************************************/ #include @@ -51,331 +51,7 @@ PUBLIC @ExInterlockedAddLargeStatistic@8 /* Return */ ret -/*ULONG - *FASTCALL - *ExfInterlockedAddUlong(IN PULONG Addend, - * IN ULONG Increment, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedAddUlong@12 -@ExfInterlockedAddUlong@12: - - /* Save flags */ - pushfd - -#ifdef CONFIG_SMP - /* Get lock address */ - mov eax, [esp+8] -.start1: -#endif - /* Disable interrupts */ - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(eax, .spin1) - - /* Do the add */ - mov eax, [ecx] - add [ecx], edx - -#ifdef CONFIG_SMP - /* Get spinlock address and release it */ - mov edx, [esp+8] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags and return */ - popfd - ret 4 - -#ifdef CONFIG_SMP -.spin1: - /* Restore flags and spin */ - popfd - pushfd - SPIN_ON_LOCK(eax, .start1) -#endif - -/*PLIST_ENTRY - *FASTCALL - *ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedInsertHeadList@12 -@ExfInterlockedInsertHeadList@12: - -#ifdef CONFIG_SMP - /* Save lock address */ - push esi - mov esi, [esp+8] -#endif - - /* Save flags and disable interrupts */ - pushfd -.start2: - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(esi, .spin2) - - /* Get list pointer */ - mov eax, [ecx] - - /* Do the insert */ - mov [edx], eax - mov [edx+4], ecx - mov [ecx], edx - mov [eax+4], edx - - /* Release lock and restore flags */ - RELEASE_SPINLOCK(esi) - popfd - -#ifdef CONFIG_SMP - pop esi -#endif - - /* Check if list was empty */ - xor eax, ecx - jz .l2 - - /* Return list pointer */ - xor eax, ecx -.l2: - ret 4 - -#ifdef CONFIG_SMP -.spin2: - popfd - pushfd - SPIN_ON_LOCK(esi, .start2) -#endif - -/*PLIST_ENTRY - *FASTCALL - *ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedInsertTailList@12 -@ExfInterlockedInsertTailList@12: - -#ifdef CONFIG_SMP - /* Save lock address */ - push esi - mov esi, [esp+8] -#endif - - /* Save flags and disable interrupts */ - pushfd -.start3: - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(esi, .spin3) - - /* Get list pointer */ - mov eax, [ecx+4] - - /* Do the insert */ - mov [edx], ecx - mov [edx+4], eax - mov [ecx+4], edx - mov [eax], edx - - /* Release lock and restore flags */ - RELEASE_SPINLOCK(esi) - popfd - -#ifdef CONFIG_SMP - pop esi -#endif - - /* Check if list was empty */ - xor eax, ecx - jz .l3 - - /* Return list pointer */ - xor eax, ecx -.l3: - ret 4 - -#ifdef CONFIG_SMP -.spin3: - popfd - pushfd - SPIN_ON_LOCK(esi, .start3) -#endif - -/*PLIST_ENTRY - *FASTCALL - *ExfInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedRemoveHeadList@8 -@ExfInterlockedRemoveHeadList@8: - - /* Save flags and disable interrupts */ -.start4: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin4) - - /* Get list pointer */ - mov eax, [ecx] - - /* Check if it's empty */ - cmp eax, ecx - je .l4 - - /* Get the next entry and do the deletion */ -#ifdef CONFIG_SMP - push ebx - mov ebx, [eax] - mov [ecx], ebx - mov [ebx+4], ecx -#else - mov edx, [eax] - mov [ecx], edx - mov [edx+4], ecx -#endif - - /* Release lock */ -#ifdef CONFIG_SMP - RELEASE_SPINLOCK(edx) - pop ebx -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret - -.l4: - /* Release lock */ - RELEASE_SPINLOCK(edx) - - /* Restore flags */ - popfd - - /* Return empty list */ - xor eax, eax - ret - -#ifdef CONFIG_SMP -.spin4: - popfd - SPIN_ON_LOCK(edx, .start4) -#endif - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedPopEntryList@8 -@ExfInterlockedPopEntryList@8: - - /* Save flags and disable interrupts */ -.start5: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin5) - - /* Get list pointer */ - mov eax, [ecx] - - /* Check if it's empty */ - or eax, eax - je .l6 - - /* Get next entry and do deletion */ -#ifdef CONFIG_SMP - push edx -#endif - mov edx, [eax] - mov [ecx], edx -#ifdef CONFIG_SMP - pop edx -#endif - -.l5: - /* Release lock */ - RELEASE_SPINLOCK(edx) - - /* Restore flags */ - popfd - - /* Return */ - ret - -.l6: - /* Return empty list */ - xor eax, eax - jmp .l5 - -#ifdef CONFIG_SMP -.spin5: - popfd - SPIN_ON_LOCK(edx, .start5) -#endif - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PSINGLE_LIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedPushEntryList@12 -@ExfInterlockedPushEntryList@12: - - /* Save flags */ - pushfd - /* Save lock pointer */ -#ifdef CONFIG_SMP - push edx - mov edx, [esp+12] -#endif - - /* Disable interrupts */ -.start6: - cli -#ifdef CONFIG_SMP - ACQUIRE_SPINLOCK(edx, .spin6) - pop edx -#endif - - /* Get list pointer */ - mov eax, [ecx] - - /* Do push */ - mov [edx], eax - mov [ecx], edx - - /* Release lock */ -#ifdef CONFIG_SMP - mov edx, [esp+8] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 4 - -#ifdef CONFIG_SMP -.spin6: - pop edx - popfd - pushfd - push edx - mov edx, [esp+12] - SPIN_ON_LOCK(edx, .start6) -#endif /*PSINGLE_LIST_ENTRY *FASTCALL @@ -505,301 +181,5 @@ PUBLIC @ExInterlockedFlushSList@4 pop ebx ret -/*INTERLOCKED_RESULT - *FASTCALL - *Exfi386InterlockedIncrementLong(IN PLONG Addend) - */ -PUBLIC @Exfi386InterlockedIncrementLong@4 -@Exfi386InterlockedIncrementLong@4: - - /* Do the op */ - LOCK add dword ptr [ecx], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret - -/*INTERLOCKED_RESULT - *FASTCALL - *Exfi386InterlockedDecrementLong(IN PLONG Addend) - */ -PUBLIC @Exfi386InterlockedDecrementLong@4 -@Exfi386InterlockedDecrementLong@4: - - /* Do the op */ - LOCK sub dword ptr [ecx], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret - -/*ULONG - *FASTCALL - *Exfi386InterlockedExchangeUlong(IN PULONG Taget, - * IN ULONG Value) - */ -PUBLIC @Exfi386InterlockedExchangeUlong@8 -@Exfi386InterlockedExchangeUlong@8: - -#ifdef CONFIG_SMP - /* On MP, do the exchange */ - xchg [ecx], edx - mov eax, edx -#else - /* On UP, use cmpxchg */ - mov eax, [ecx] -.l11: - cmpxchg [ecx], edx - jnz .l11 -#endif - - /* Return */ - ret - -/*PVOID - *FASTCALL - *ExfInterlockedCompareExchange64(IN PLONGLONG Destination, - * IN PLONGLONG Exchange, - * IN PLONGLONG Comperand) - */ -PUBLIC @ExfInterlockedCompareExchange64@12 -@ExfInterlockedCompareExchange64@12: - - /* Save registers */ - push ebx - push ebp - - /* Get destination pointer, exchange value and comperand value/address */ - mov ebp, ecx - mov ebx, [edx] - mov ecx, [edx+4] - mov edx, [esp+12] - mov eax, [edx] - mov edx, [edx+4] - - /* Do the op */ - LOCK cmpxchg8b qword ptr [ebp] - - /* Restore volatiles */ - pop ebp - pop ebx - - /* Return */ - ret 4 - -/*PVOID - *FASTCALL - *ExfInterlockedCompareExchange64(IN PLONGLONG Destination, - * IN PLONGLONG Exchange, - * IN PLONGLONG Comperand, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExInterlockedCompareExchange64@16 -@ExInterlockedCompareExchange64@16: - - /* Save registers */ - push ebp - push ebp - - /* Get destination pointer, exchange value and comperand value/address */ - mov ebp, ecx - mov ebx, [edx] - mov ecx, [edx+4] - mov edx, [esp+12] - mov eax, [edx] - mov edx, [edx+4] - - /* Do the op */ - LOCK cmpxchg8b qword ptr [ebp] - - /* Restore volatiles */ - pop ebp - pop ebx - - /* Return */ - ret 8 - -/*** Non-586 functions ***/ - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPopEntrySList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedPopEntrySList@8 -@ExfInterlockedPopEntrySList@8: - - /* Save flags */ -.starta: - pushfd - - /* Disable interrupts */ - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(edx, .spina) - - /* Get the next link and check if it's empty */ - mov eax, [ecx] - or eax, eax - jz .l12 - - /* Get address of the next link and store it */ - push [eax] - pop [ecx] - - /* Decrement list depth */ - dec dword ptr [ecx+4] - -.l12: -#ifdef CONFIG_SMP - /* Release spinlock */ - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags and return */ - popfd - ret 0 - -#ifdef CONFIG_SMP -.spina: - /* Restore flags and spin */ - popfd - SPIN_ON_LOCK(edx, .starta) -#endif - -/*PSINGLE_LIST_ENTRY - *FASTCALL - *ExfInterlockedPushEntrySList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PSINGLE_LIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExfInterlockedPushEntrySList@12 -@ExfInterlockedPushEntrySList@12: - - /* Save flags */ -.startb: - pushfd - - /* Disable interrupts */ - cli - - /* Acquire lock */ -#ifndef CONFIG_SMP - mov eax, [esp+8] - ACQUIRE_SPINLOCK(eax, .spinb) -#endif - - /* Get the next link and check if it's empty */ - push [ecx] - - /* Get address of the next link and store it */ - pop [edx] - mov [ecx], edx - - /* Increment list depth */ - inc dword ptr [ecx+4] - -#ifdef CONFIG_SMP - /* Release spinlock */ - RELEASE_SPINLOCK(eax) -#endif - - /* Restore flags and return */ - popfd - ret 4 - -#ifdef CONFIG_SMP -.spinb: - /* Restore flags and spin */ - popfd - SPIN_ON_LOCK(eax, .startb) -#endif - -/*PVOID - *FASTCALL - *ExpInterlockedCompareExchange64(IN PLONGLONG Destination, - * IN PLONGLONG Exchange, - * IN PLONGLONG Comperand, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC @ExpInterlockedCompareExchange64@16 -@ExpInterlockedCompareExchange64@16: - - /* Save registers */ - push ebp - push ebp - - /* Get destination pointer, exchange value and comperand value/address */ - mov ebp, ecx - mov ebx, [edx] - mov ecx, [edx+4] - mov edx, [esp+12] - mov eax, [edx] - mov edx, [edx+4] - -#ifdef CONFIG_SMP - /* Save ESI so we can store KSPINLOCK in it */ - push esi - - /* Save flags and lock, and disable interrupts */ - pushfd - mov esi, [esp+24] -.startc: - cli - - /* Acquire the spinlock */ - ACQUIRE_SPINLOCK(esi, .spinc) -#else - /* Save flags and disable interrupts */ - pushfd - cli -#endif - - /* Compare bottom */ - cmp eax, [ebp] - jne NoMatch - - /* Compare top */ - cmp edx, [ebp+4] - jne NoMatch - - /* Save new value */ - mov [ebp], ebx - mov [ebp+4], ecx - -AfterSave: -#ifdef CONFIG_SMP - /* Release lock, restore volatiles and flags */ - RELEASE_SPINLOCK(esi) - popfd - pop esi -#else - popfd -#endif - - /* Restore the other volatiles and return */ - pop ebp - pop ebx - - /* Return */ - ret 8 - -NoMatch: - /* Return the current value */ - mov eax, [ebp] - mov edx, [ebp+4] - jmp AfterSave - -#ifdef CONFIG_SMP -.spinc: - /* Restore flags and spin */ - popfd - pushfd - SPIN_ON_LOCK(esi, .startc) -#endif - END /* EOF */ diff --git a/ntoskrnl/ex/i386/interlck_asm.S b/ntoskrnl/ex/i386/interlck_asm.S deleted file mode 100644 index 755813e80d8..00000000000 --- a/ntoskrnl/ex/i386/interlck_asm.S +++ /dev/null @@ -1,564 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ex/i386/interlck_asm.S - * PURPOSE: STDCALL Interlocked Functions - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - */ - -/* INCLUDES ******************************************************************/ - -#include -#include -#include - -/* FUNCTIONS ****************************************************************/ - -.code32 - -/* - * NOTE: These functions must obey the following rules: - * - Acquire locks only on MP systems. - * - Be safe at HIGH_LEVEL (no paged access). - * - Preserve flags. - * - Disable interrups. - */ - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedAddLargeInteger(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedAddLargeInteger@16 -_ExInterlockedAddLargeInteger@16: - - /* Prepare stack frame */ - push ebp - mov ebp, esp - sub esp, 8 - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov eax, [ebp+20] -#endif - - /* Save flags and disable interrupts */ -.start1: - pushfd - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(eax, .spin1) - - /* Do the calculation */ - mov eax, [ebp+8] - mov ecx, [eax] - mov edx, [eax+4] - - /* Save result */ - mov [ebp-8], ecx - mov [ebp-4], edx - - /* Add increment */ - add ecx, [ebp+12] - adc edx, [ebp+16] - - /* Save result */ - mov [eax], ecx - mov [eax+4], edx - - /* Release lock */ -#ifdef CONFIG_SMP - mov eax, [ebp+20] - RELEASE_SPINLOCK(eax) -#endif - - /* Restore flags */ - popfd - - /* Restore frame and return values */ - mov eax, [ebp-8] - mov edx, [ebp-4] - mov esp, ebp - pop ebp - ret 16 - -#ifdef CONFIG_SMP -.spin1: - popfd - SPIN_ON_LOCK(eax, .start1) -#endif - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedAddUlong@12 -_ExInterlockedAddUlong@12: - - /* Save flags and disable interrupts */ - pushfd - - /* Get lock address */ -#ifdef CONFIG_SMP - mov edx, [ebp+16] -#endif -.start2: - cli - - /* Acquire lock */ - ACQUIRE_SPINLOCK(edx, .spin2) - - /* Do the calculation */ - mov ecx, [esp+8] -#ifdef CONFIG_SMP - mov eax, [ecx] - add eax, [esp+12] - - /* Save result */ - mov [ecx], eax -#else - - /* Do the calculation */ - mov edx, [ecx] - mov eax, edx - add edx, [esp+12] - - /* Save result */ - mov [ecx], edx -#endif - - /* Release lock, restore flags and return */ -#ifdef CONFIG_SMP - sub eax, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - popfd - ret 12 - -#ifdef CONFIG_SMP -.spin2: - popfd - pushfd - SPIN_ON_LOCK(eax, .start2) -#endif - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedInsertHeadList@12 -_ExInterlockedInsertHeadList@12: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+12] -#endif - - /* Save flags and disable interrupts */ -.start3: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin3) - - /* Get list pointers */ - mov eax, [esp+8] - mov ecx, [esp+12] - mov edx, [eax] - - /* Do the insert */ - mov [ecx], edx - mov [ecx+4], eax - mov [eax], ecx - mov [edx+4], ecx - - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+16] - RELEASE_SPINLOCK(ecx) -#endif - - /* Restore flags */ - popfd - - /* check if the list was empty and return NULL */ - xor eax, edx - jz .l2 - - /* Return pointer */ - mov eax, edx - -.l2: - ret 12 - -#ifdef CONFIG_SMP -.spin3: - popfd - SPIN_ON_LOCK(edx, .start3) -#endif - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedInsertTailList(IN PLIST_ENTRY ListHead, - * IN PLIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedInsertTailList@12 -_ExInterlockedInsertTailList@12: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+12] -#endif - - /* Save flags and disable interrupts */ -.start4: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin4) - - /* Get list pointers */ - mov eax, [esp+8] - mov ecx, [esp+12] - mov edx, [eax+4] - - /* Do the insert */ - mov [ecx], eax - mov [ecx+4], edx - mov [eax+4], ecx - mov [edx], ecx - - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+16] - RELEASE_SPINLOCK(ecx) -#endif - - /* Restore flags */ - popfd - - /* Check if the list was empty and return NULL */ - xor eax, edx - jz .l3 - - /* Return pointer */ - mov eax, edx - -.l3: - ret 12 - -#ifdef CONFIG_SMP -.spin4: - popfd - SPIN_ON_LOCK(edx, .start4) -#endif - -/*PLIST_ENTRY - *NTAPI - *ExInterlockedRemoveHeadList(IN PLIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedRemoveHeadList@8 -_ExInterlockedRemoveHeadList@8: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+8] -#endif - - /* Save flags and disable interrupts */ -.start5: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin5) - - /* Get list pointers */ - mov edx, [esp+8] - mov eax, [edx] - - /* Check if it's empty */ - cmp eax, edx - je .l4 - - /* Get next entry and do deletion */ - mov ecx, [eax] - mov [edx], ecx - mov [ecx+4], edx - - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 8 - -.l4: - /* Release lock */ -#ifdef CONFIG_SMP - mov edx, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return empty list */ - xor eax, eax - ret 8 - -#ifdef CONFIG_SMP -.spin5: - popfd - SPIN_ON_LOCK(edx, .start5) -#endif - -/*PSINGLE_LIST_ENTRY - *NTAPI - *ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedPopEntryList@8 -_ExInterlockedPopEntryList@8: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+8] -#endif - - /* Save flags and disable interrupts */ -.start6: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin6) - - /* Get list pointers */ - mov edx, [esp+8] - mov eax, [ecx] - - /* Check if it's empty */ - or eax, eax - je .l6 - - /* Get next entry and do deletion */ - mov edx, [eax] - mov [ecx], edx - -.l5: - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+12] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 8 - -.l6: - /* Return empty list */ - xor eax, eax - jmp .l5 - -#ifdef CONFIG_SMP -.spin6: - popfd - SPIN_ON_LOCK(edx, .start6) -#endif - -/*PSINGLE_LIST_ENTRY - *NTAPI - *ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, - * IN PSINGLE_LIST_ENTRY ListEntry, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedPushEntryList@12 -_ExInterlockedPushEntryList@12: - - /* Save lock pointer */ -#ifdef CONFIG_SMP - mov edx, [esp+12] -#endif - - /* Save flags and disable interrupts */ -.start7: - pushfd - cli - ACQUIRE_SPINLOCK(edx, .spin7) - - /* Get list pointers */ - mov edx, [esp+8] - mov eax, [edx] - mov ecx, [esp+12] - - /* Do push */ - mov [ecx], eax - mov [edx], ecx - - /* Release lock */ -#ifdef CONFIG_SMP - mov ecx, [esp+16] - RELEASE_SPINLOCK(edx) -#endif - - /* Restore flags */ - popfd - - /* Return */ - ret 12 - -#ifdef CONFIG_SMP -.spin7: - popfd - SPIN_ON_LOCK(edx, .start7) -#endif - -/*INTERLOCKED_RESULT - *NTAPI - *ExInterlockedIncrementLong(IN PLONG Addend, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedIncrementLong@8 -_ExInterlockedIncrementLong@8: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK add dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 8 - -/*INTERLOCKED_RESULT - *NTAPI - *ExInterlockedDecrementLong(IN PLONG Addend, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedDecrementLong@8 -_ExInterlockedDecrementLong@8: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK sub dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 8 - -/*ULONG - *NTAPI - *ExInterlockedExchangeUlong(IN PULONG Target, - * IN ULONG Value, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _ExInterlockedExchangeUlong@12 -_ExInterlockedExchangeUlong@12: - - /* Get pointers */ - mov edx, [esp+4] - mov eax, [esp+8] - -#ifdef CONFIG_SMP - /* On MP, do the exchange */ - xchg [edx], eax -#else - /* On UP, disable interrupts and save flags */ - pushfd - cli - - /* Switch values */ - mov eax, [edx] - mov [edx], ecx - popfd -#endif - - /* Return */ - ret 12 - -/*INTERLOCKED_RESULT - *NTAPI - *Exi386InterlockedIncrementLong(IN PLONG Addend, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _Exi386InterlockedIncrementLong@4 -_Exi386InterlockedIncrementLong@4: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK add dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 4 - -/*INTERLOCKED_RESULT - *NTAPI - *Exi386InterlockedDecrementLong(IN PLONG Addend, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _Exi386InterlockedDecrementLong@4 -_Exi386InterlockedDecrementLong@4: - - /* Get addend */ - mov eax, [esp+4] - - /* Do the op */ - LOCK sub dword ptr [eax], 1 - - /* Return */ - lahf - and eax, EFLAG_SELECT - ret 8 - -/*ULONG - *NTAPI - *Exi386InterlockedExchangeUlong(IN PULONG Target, - * IN ULONG Value, - * IN PKSPIN_LOCK Lock) - */ -PUBLIC _Exi386InterlockedExchangeUlong@12 -_Exi386InterlockedExchangeUlong@12: - - /* Get pointers */ - mov edx, [esp+4] - mov eax, [esp+8] - -#ifdef CONFIG_SMP - /* On MP, do the exchange */ - xchg [edx], eax -#else - /* On UP, disable interrupts and save flags */ - pushfd - cli - - /* Switch values */ - mov eax, [edx] - mov [edx], ecx - popfd -#endif - - /* Return */ - ret 8 - -END -/* EOF */ diff --git a/ntoskrnl/ex/init.c b/ntoskrnl/ex/init.c index ab2283d58aa..b0e93126d07 100644 --- a/ntoskrnl/ex/init.c +++ b/ntoskrnl/ex/init.c @@ -10,6 +10,7 @@ /* INCLUDES ******************************************************************/ #include +#include #define NDEBUG #include diff --git a/ntoskrnl/ex/interlocked.c b/ntoskrnl/ex/interlocked.c new file mode 100644 index 00000000000..65b3872bee2 --- /dev/null +++ b/ntoskrnl/ex/interlocked.c @@ -0,0 +1,545 @@ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/ex/interlocked.c +* PURPOSE: Interlocked functions +* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) +*/ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#undef ExInterlockedAddUlong +#undef ExInterlockedInsertHeadList +#undef ExInterlockedInsertTailList +#undef ExInterlockedRemoveHeadList +#undef ExInterlockedPopEntryList +#undef ExInterlockedPushEntryList +#undef ExInterlockedIncrementLong +#undef ExInterlockedDecrementLong +#undef ExInterlockedExchangeUlong +#undef ExInterlockedCompareExchange64 + + +/* FUNCTIONS ****************************************************************/ + +FORCEINLINE +BOOLEAN +_ExiDisableInteruptsAndAcquireSpinlock( + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enabled; + + /* Disable interrupts */ + Enabled = KeDisableInterrupts(); + + /* Acquire the spinlock (inline) */ + KxAcquireSpinLock(Lock); + + return Enabled; +} + +FORCEINLINE +VOID +_ExiReleaseSpinLockAndRestoreInterupts( + IN OUT PKSPIN_LOCK Lock, + BOOLEAN Enable) +{ + /* Release the spinlock */ + KxReleaseSpinLock(Lock); + + /* Restore interrupts */ + KeRestoreInterrupts(Enable); +} + + +LARGE_INTEGER +NTAPI +ExInterlockedAddLargeInteger( + IN OUT PLARGE_INTEGER Addend, + IN LARGE_INTEGER Increment, + IN OUT PKSPIN_LOCK Lock) +{ + LARGE_INTEGER OldValue; + BOOLEAN Enable; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old value */ + OldValue.QuadPart = Addend->QuadPart; + + /* Do the operation */ + Addend->QuadPart += Increment.QuadPart; + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old value */ + return OldValue; +} + +ULONG +NTAPI +ExInterlockedAddUlong( + IN OUT PULONG Addend, + IN ULONG Increment, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + ULONG OldValue; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old value */ + OldValue = *Addend; + + /* Do the operation */ + *Addend += Increment; + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old value */ + return OldValue; +} + +PLIST_ENTRY +NTAPI +ExInterlockedInsertHeadList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PLIST_ENTRY FirstEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the first entry */ + FirstEntry = ListHead->Flink; + + /* Insert the new entry */ + InsertHeadList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old first entry or NULL for empty list */ + return (FirstEntry == ListHead) ? NULL : FirstEntry; +} + +PLIST_ENTRY +NTAPI +ExInterlockedInsertTailList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PLIST_ENTRY LastEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the last entry */ + LastEntry = ListHead->Blink; + + /* Insert the new entry */ + InsertTailList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old last entry or NULL for empty list */ + return (LastEntry == ListHead) ? NULL : LastEntry; +} + +PLIST_ENTRY +NTAPI +ExInterlockedRemoveHeadList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PLIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Check if the list is empty */ + if (IsListEmpty(ListHead)) + { + /* Return NULL */ + ListEntry = NULL; + } + else + { + /* Remove the first entry from the list head */ + ListEntry = RemoveHeadList(ListHead); + } + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +NTAPI +ExInterlockedPopEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PSINGLE_LIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Pop the first entry from the list */ + ListEntry = PopEntryList(ListHead); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +NTAPI +ExInterlockedPushEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN OUT PSINGLE_LIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PSINGLE_LIST_ENTRY OldListEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old top entry */ + OldListEntry = ListHead->Next; + + /* Push a new entry on the list */ + PushEntryList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the entry */ + return OldListEntry; +} + +INTERLOCKED_RESULT +NTAPI +ExInterlockedIncrementLong( + IN PLONG Addend, + IN PKSPIN_LOCK Lock) +{ + LONG Result; + + Result = _InterlockedIncrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +NTAPI +ExInterlockedDecrementLong( + IN PLONG Addend, + IN PKSPIN_LOCK Lock) +{ + LONG Result; + + Result = _InterlockedDecrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +ULONG +NTAPI +ExInterlockedExchangeUlong( + IN PULONG Target, + IN ULONG Value, + IN PKSPIN_LOCK Lock) +{ + return (ULONG)_InterlockedExchange((PLONG)Target, (LONG)Value); +} + +#ifdef _M_IX86 + +ULONG +FASTCALL +ExfInterlockedAddUlong( + IN OUT PULONG Addend, + IN ULONG Increment, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + ULONG OldValue; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old value */ + OldValue = *Addend; + + /* Do the operation */ + *Addend += Increment; + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old value */ + return OldValue; +} + +PLIST_ENTRY +FASTCALL +ExfInterlockedInsertHeadList( + IN OUT PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PLIST_ENTRY FirstEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the first entry */ + FirstEntry = ListHead->Flink; + + /* Insert the new entry */ + InsertHeadList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old first entry or NULL for empty list */ + return (FirstEntry == ListHead) ? NULL : FirstEntry; +} + +PLIST_ENTRY +FASTCALL +ExfInterlockedInsertTailList( + IN OUT PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PLIST_ENTRY LastEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the last entry */ + LastEntry = ListHead->Blink; + + /* Insert the new entry */ + InsertTailList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* Return the old last entry or NULL for empty list */ + return (LastEntry == ListHead) ? NULL : LastEntry; +} + + +PLIST_ENTRY +FASTCALL +ExfInterlockedRemoveHeadList( + IN OUT PLIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PLIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Check if the list is empty */ + if (IsListEmpty(ListHead)) + { + /* Return NULL */ + ListEntry = NULL; + } + else + { + /* Remove the first entry from the list head */ + ListEntry = RemoveHeadList(ListHead); + } + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +FASTCALL +ExfInterlockedPopEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PSINGLE_LIST_ENTRY ListEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Pop the first entry from the list */ + ListEntry = PopEntryList(ListHead); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* return the entry */ + return ListEntry; +} + +PSINGLE_LIST_ENTRY +FASTCALL +ExfInterlockedPushEntryList( + IN OUT PSINGLE_LIST_ENTRY ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN OUT PKSPIN_LOCK Lock) +{ + BOOLEAN Enable; + PSINGLE_LIST_ENTRY OldListEntry; + + /* Disable interrupts and acquire the spinlock */ + Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock); + + /* Save the old top entry */ + OldListEntry = ListHead->Next; + + /* Push a new entry on the list */ + PushEntryList(ListHead, ListEntry); + + /* Release the spinlock and restore interrupts */ + _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable); + + /* return the entry */ + return OldListEntry; +} + +INTERLOCKED_RESULT +NTAPI +Exi386InterlockedIncrementLong( + IN PLONG Addend) +{ + LONG Result; + + Result = _InterlockedIncrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +FASTCALL +Exfi386InterlockedIncrementLong( + IN OUT LONG volatile *Addend) +{ + LONG Result; + + Result = _InterlockedIncrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +NTAPI +Exi386InterlockedDecrementLong( + IN PLONG Addend) +{ + LONG Result; + + Result = _InterlockedDecrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +INTERLOCKED_RESULT +FASTCALL +Exfi386InterlockedDecrementLong( + IN OUT PLONG Addend) +{ + LONG Result; + + Result = _InterlockedDecrement(Addend); + return (Result < 0) ? ResultNegative : + (Result > 0) ? ResultPositive : + ResultZero; +} + +LONG +NTAPI +Exi386InterlockedExchangeUlong( + PLONG Target, + LONG Exchange) +{ + return _InterlockedExchange(Target, Exchange); +} + +ULONG +FASTCALL +Exfi386InterlockedExchangeUlong( + IN OUT PULONG Target, + IN ULONG Exchange) +{ + return _InterlockedExchange((PLONG)Target, Exchange); +} + +LONGLONG +FASTCALL +ExInterlockedCompareExchange64( + IN OUT LONGLONG volatile *Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand, + IN PKSPIN_LOCK Lock) +{ + return _InterlockedCompareExchange64(Destination, *Exchange, *Comparand); +} + +LONGLONG +FASTCALL +ExfInterlockedCompareExchange64( + IN OUT LONGLONG volatile *Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand) +{ + return _InterlockedCompareExchange64(Destination, *Exchange, *Comparand); +} +#endif + +#if 0 + +VOID +FASTCALL +ExInterlockedAddLargeStatistic( + IN OUT PLARGE_INTEGER Addend, + IN ULONG Increment) +{ +} + + +#endif + diff --git a/ntoskrnl/ex/resource.c b/ntoskrnl/ex/resource.c index cf179ffca0c..1d33a45e322 100644 --- a/ntoskrnl/ex/resource.c +++ b/ntoskrnl/ex/resource.c @@ -1159,7 +1159,7 @@ TryAcquire: { /* Release the lock and return */ ExReleaseResourceLock(Resource, &LockHandle); - return TRUE; + return FALSE; } /* Check if we have a shared waiters semaphore */ @@ -1276,7 +1276,7 @@ TryAcquire: { /* So bail out if we're not allowed */ ExReleaseResourceLock(Resource, &LockHandle); - return TRUE; + return FALSE; } /* Check if we have a shared waiters semaphore */ @@ -1359,7 +1359,7 @@ TryAcquire: { /* So bail out if we're not allowed */ ExReleaseResourceLock(Resource, &LockHandle); - return TRUE; + return FALSE; } /* Check if we have a shared waiters semaphore */ diff --git a/ntoskrnl/fstub/disksup.c b/ntoskrnl/fstub/disksup.c index 05cc18f79bc..72643f87e4e 100644 --- a/ntoskrnl/fstub/disksup.c +++ b/ntoskrnl/fstub/disksup.c @@ -398,7 +398,7 @@ xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName, /* Read the partition table */ Status = IoReadPartitionTable(DeviceObject, DiskGeometry.BytesPerSector, - FALSE, + TRUE, LayoutInfo); } diff --git a/ntoskrnl/include/internal/amd64/ke.h b/ntoskrnl/include/internal/amd64/ke.h index bbad6b89771..f0ab9086abb 100644 --- a/ntoskrnl/include/internal/amd64/ke.h +++ b/ntoskrnl/include/internal/amd64/ke.h @@ -134,6 +134,31 @@ extern ULONG KeI386CpuStep; #define KeGetTrapFrameInterruptState(TrapFrame) \ BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK) +/* Diable interrupts and return whether they were enabled before */ +BOOLEAN +NTAPI +KeDisableInterrupts(VOID) +{ + ULONG Flags; + BOOLEAN Return; + + /* Get EFLAGS and check if the interrupt bit is set */ + Flags = __readeflags(); + Return = (Flags & EFLAGS_INTERRUPT_MASK) ? TRUE: FALSE; + + /* Disable interrupts */ + _disable(); + return Return; +} + +/* Restore previous interrupt state */ +FORCEINLINE +VOID +KeRestoreInterrupts(BOOLEAN WereEnabled) +{ + if (WereEnabled) _enable(); +} + // // Invalidates the TLB entry for a specified address // diff --git a/ntoskrnl/include/internal/arm/ke.h b/ntoskrnl/include/internal/arm/ke.h index 3fbe4eb3ad9..1b5f72c6a94 100644 --- a/ntoskrnl/include/internal/arm/ke.h +++ b/ntoskrnl/include/internal/arm/ke.h @@ -65,6 +65,31 @@ // //#define KeGetTrapFrameInterruptState(TrapFrame) +FORCEINLINE +BOOLEAN +KeDisableInterrupts(VOID) +{ + ARM_STATUS_REGISTER Flags; + + // + // Get current interrupt state and disable interrupts + // + Flags = KeArmStatusRegisterGet(); + _disable(); + + // + // Return previous interrupt state + // + return Flags.IrqDisable; +} + +FORCEINLINE +VOID +KeRestoreInterrupts(BOOLEAN WereEnabled) +{ + if (WereEnabled) _enable(); +} + // // Invalidates the TLB entry for a specified address // diff --git a/ntoskrnl/include/internal/cm.h b/ntoskrnl/include/internal/cm.h index c70e9c064ae..619455b6fac 100644 --- a/ntoskrnl/include/internal/cm.h +++ b/ntoskrnl/include/internal/cm.h @@ -33,7 +33,7 @@ if (x & CmpTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define CMTRACE(x, ...) DPRINT(__VA_ARGS__) +#define CMTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/internal/dbgk.h b/ntoskrnl/include/internal/dbgk.h index 457fcf0e5bf..d1e8f814c2a 100644 --- a/ntoskrnl/include/internal/dbgk.h +++ b/ntoskrnl/include/internal/dbgk.h @@ -43,7 +43,7 @@ } #endif #else -#define DBGKTRACE(x, ...) DPRINT(__VA_ARGS__) +#define DBGKTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif VOID diff --git a/ntoskrnl/include/internal/fsrtl.h b/ntoskrnl/include/internal/fsrtl.h index b0777de94cc..16bb399a893 100644 --- a/ntoskrnl/include/internal/fsrtl.h +++ b/ntoskrnl/include/internal/fsrtl.h @@ -36,7 +36,7 @@ if (x & FsRtlpTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define FSTRACE(x, ...) DPRINT(__VA_ARGS__) +#define FSTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/internal/hdl.h b/ntoskrnl/include/internal/hdl.h index d93b520fa3c..349a9070f7b 100644 --- a/ntoskrnl/include/internal/hdl.h +++ b/ntoskrnl/include/internal/hdl.h @@ -30,7 +30,7 @@ if (x & HdlpTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define HDLTRACE(x, ...) DPRINT(__VA_ARGS__) +#define HDLTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/internal/i386/asmmacro.S b/ntoskrnl/include/internal/i386/asmmacro.S index aeb67fcd417..77d989e9011 100644 --- a/ntoskrnl/include/internal/i386/asmmacro.S +++ b/ntoskrnl/include/internal/i386/asmmacro.S @@ -217,11 +217,18 @@ MACRO(KiCallHandler, Handler) ENDM MACRO(TRAP_ENTRY, Trap, Flags) -EXTERN @&Trap&Handler@4 :PROC + EXTERN @&Trap&Handler@4 :PROC PUBLIC _&Trap - _&Trap: - KiEnterTrap Flags - KiCallHandler @&Trap&Handler@4 + .PROC &Trap + /* Generate proper debugging symbols */ + FPO 0, 0, 0, 0, 1, FRAME_TRAP + + /* Common code to create the trap frame */ + KiEnterTrap Flags + + /* Call the C handler */ + KiCallHandler @&Trap&Handler@4 + .ENDP &Trap ENDM #define KI_RESTORE_EAX HEX(001) diff --git a/ntoskrnl/include/internal/i386/ke.h b/ntoskrnl/include/internal/i386/ke.h index 8e701abac7c..f4fe39b97d7 100644 --- a/ntoskrnl/include/internal/i386/ke.h +++ b/ntoskrnl/include/internal/i386/ke.h @@ -164,6 +164,31 @@ typedef struct _KV8086_STACK_FRAME KV86_FRAME V86Frame; } KV8086_STACK_FRAME, *PKV8086_STACK_FRAME; +/* Diable interrupts and return whether they were enabled before */ +FORCEINLINE +BOOLEAN +KeDisableInterrupts(VOID) +{ + ULONG Flags; + BOOLEAN Return; + + /* Get EFLAGS and check if the interrupt bit is set */ + Flags = __readeflags(); + Return = (Flags & EFLAGS_INTERRUPT_MASK) ? TRUE: FALSE; + + /* Disable interrupts */ + _disable(); + return Return; +} + +/* Restore previous interrupt state */ +FORCEINLINE +VOID +KeRestoreInterrupts(BOOLEAN WereEnabled) +{ + if (WereEnabled) _enable(); +} + // // Registers an interrupt handler with an IDT vector // @@ -457,6 +482,7 @@ extern VOID __cdecl KiTrap08(VOID); extern VOID __cdecl KiTrap13(VOID); extern VOID __cdecl KiFastCallEntry(VOID); extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID); +extern VOID NTAPI ExpInterlockedPopEntrySListResume(VOID); extern VOID __cdecl CopyParams(VOID); extern VOID __cdecl ReadBatch(VOID); extern VOID __cdecl FrRestore(VOID); @@ -733,13 +759,12 @@ KiConvertToGuiThread(VOID) */ __asm__ __volatile__ ( - "movl %%ebp, %1\n" - "subl %%esp, %1\n" - "call _PsConvertToGuiThread@0\n" - "addl %%esp, %1\n" - "movl %1, %%ebp\n" - "movl %%eax, %0\n" - : "=r"(Result), "=r"(StackFrame) + "movl %%ebp, %1\n\t" + "subl %%esp, %1\n\t" + "call _PsConvertToGuiThread@0\n\t" + "addl %%esp, %1\n\t" + "movl %1, %%ebp" + : "=a"(Result), "=r"(StackFrame) : : "%esp", "%ecx", "%edx", "memory" ); @@ -845,4 +870,11 @@ Ki386PerfEnd(VOID) KeGetContextSwitches(KeGetCurrentPrcb())); } +FORCEINLINE +PULONG +KiGetUserModeStackAddress(void) +{ + return &(KeGetCurrentThread()->TrapFrame->HardwareEsp); +} + #endif diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h index 2649e3ed564..cbcf466b00c 100644 --- a/ntoskrnl/include/internal/io.h +++ b/ntoskrnl/include/internal/io.h @@ -10,7 +10,7 @@ // // Define this if you want debugging support // -#define _IO_DEBUG_ 0x00 +#define _IO_DEBUG_ 0x01 // // These define the Debug Masks Supported @@ -43,7 +43,7 @@ } #endif #else -#define IOTRACE(x, ...) DPRINT(__VA_ARGS__) +#define IOTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/internal/ke.h b/ntoskrnl/include/internal/ke.h index 56f3ee013c2..1dbb1f48e28 100644 --- a/ntoskrnl/include/internal/ke.h +++ b/ntoskrnl/include/internal/ke.h @@ -164,7 +164,7 @@ extern VOID __cdecl KiInterruptTemplate(VOID); #define TIMER_WAIT_BLOCK 0x3L #ifdef _M_ARM // FIXME: remove this once our headers are cleaned up -// +// // A system call ID is formatted as such: // .________________________________________________________________. // | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | @@ -187,7 +187,7 @@ extern VOID __cdecl KiInterruptTemplate(VOID); // // NB. From assembly code, the table number must be computed as an offset into // the service descriptor table. -// +// // Each entry into the table is 16 bytes long on 32-bit architectures, and // 32 bytes long on 64-bit architectures. // @@ -864,7 +864,7 @@ KeBugCheckWithTf( ULONG_PTR BugCheckParameter4, PKTRAP_FRAME Tf ); - + BOOLEAN NTAPI KiHandleNmi(VOID); @@ -1020,12 +1020,6 @@ KiCallUserMode( IN PULONG OutputLength ); -PULONG -NTAPI -KiGetUserModeStackAddress( - VOID -); - VOID NTAPI KiInitMachineDependent(VOID); @@ -1039,12 +1033,6 @@ VOID NTAPI KeThawExecution(IN BOOLEAN Enable); -BOOLEAN -NTAPI -KeDisableInterrupts( - VOID -); - VOID FASTCALL KeAcquireQueuedSpinLockAtDpcLevel( diff --git a/ntoskrnl/include/internal/lpc.h b/ntoskrnl/include/internal/lpc.h index ad5ecba6699..34392c4c185 100644 --- a/ntoskrnl/include/internal/lpc.h +++ b/ntoskrnl/include/internal/lpc.h @@ -46,7 +46,7 @@ } #endif #else -#define LPCTRACE(x, ...) DPRINT(__VA_ARGS__) +#define LPCTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index eec33616a54..803dc81b5a7 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -6,6 +6,7 @@ struct _EPROCESS; +extern PMMSUPPORT MmKernelAddressSpace; extern PFN_NUMBER MiFreeSwapPages; extern PFN_NUMBER MiUsedSwapPages; extern SIZE_T MmTotalPagedPoolQuota; @@ -1119,10 +1120,6 @@ BOOLEAN NTAPI MmIsDirtyPageRmap(PFN_NUMBER Page); -NTSTATUS -NTAPI -MmWritePagePhysicalAddress(PFN_NUMBER Page); - NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page); @@ -1138,7 +1135,7 @@ MiGetPfnEntry(IN PFN_NUMBER Pfn) /* Make sure the PFN number is valid */ if (Pfn > MmHighestPhysicalPage) return NULL; - + /* Make sure this page actually has a PFN entry */ if ((MiPfnBitMap.Buffer) && !(RtlTestBit(&MiPfnBitMap, (ULONG)Pfn))) return NULL; @@ -1342,7 +1339,7 @@ MmRawDeleteVirtualMapping(PVOID Address); VOID NTAPI MmGetPageFileMapping( - struct _EPROCESS *Process, + struct _EPROCESS *Process, PVOID Address, SWAPENTRY* SwapEntry); @@ -1739,7 +1736,15 @@ MmCallDllInitialize( IN PLIST_ENTRY ListHead ); -extern PMMSUPPORT MmKernelAddressSpace; + +/* procsup.c *****************************************************************/ + +NTSTATUS +NTAPI +MmGrowKernelStack( + IN PVOID StackPointer +); + FORCEINLINE VOID diff --git a/ntoskrnl/include/internal/ob.h b/ntoskrnl/include/internal/ob.h index 532565ee390..cd690958549 100644 --- a/ntoskrnl/include/internal/ob.h +++ b/ntoskrnl/include/internal/ob.h @@ -31,7 +31,7 @@ if (x & ObpTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define OBTRACE(x, ...) DPRINT(__VA_ARGS__) +#define OBTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/internal/po.h b/ntoskrnl/include/internal/po.h index 903812fb6ce..dcc4d0dbcbb 100644 --- a/ntoskrnl/include/internal/po.h +++ b/ntoskrnl/include/internal/po.h @@ -30,7 +30,7 @@ if (x & PopTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define POTRACE(x, ...) DPRINT(__VA_ARGS__) +#define POTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif typedef struct _PO_HIBER_PERF diff --git a/ntoskrnl/include/internal/ps.h b/ntoskrnl/include/internal/ps.h index bf18cf818b3..af02c4557f9 100644 --- a/ntoskrnl/include/internal/ps.h +++ b/ntoskrnl/include/internal/ps.h @@ -54,7 +54,7 @@ __LINE__, \ OBJECT_TO_OBJECT_HEADER(x)->PointerCount) #else -#define PSTRACE(x, ...) DPRINT(__VA_ARGS__) +#define PSTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #define PSREFTRACE(x) #endif diff --git a/ntoskrnl/include/internal/vdm.h b/ntoskrnl/include/internal/vdm.h index 5934fc535ef..5ff64e1a055 100644 --- a/ntoskrnl/include/internal/vdm.h +++ b/ntoskrnl/include/internal/vdm.h @@ -27,7 +27,7 @@ if (x & VdmpTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define VMTRACE(x, ...) DPRINT(__VA_ARGS__) +#define VMTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) #endif // diff --git a/ntoskrnl/include/ntoskrnl.h b/ntoskrnl/include/ntoskrnl.h index ed37af715e6..84937f2168d 100644 --- a/ntoskrnl/include/ntoskrnl.h +++ b/ntoskrnl/include/ntoskrnl.h @@ -38,9 +38,7 @@ #define TEXT(s) L##s #include #include - -/* FIXME: Temporary until Winldr is used */ -#include +#include /* C Headers */ #include @@ -53,7 +51,6 @@ #include /* ReactOS Headers */ -#include #include /* SetupLDR Support */ diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c index 79b4ab73391..a95aee9e22a 100644 --- a/ntoskrnl/io/iomgr/driver.c +++ b/ntoskrnl/io/iomgr/driver.c @@ -850,7 +850,6 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry) DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); return(Status); } - DeviceNode->ServiceName = ServiceName; /* * Initialize the driver @@ -1834,8 +1833,6 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) cur--; } - IopDisplayLoadingMessage(&ServiceName); - /* * Get service type. */ @@ -1882,21 +1879,6 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) DPRINT("FullImagePath: '%wZ'\n", &ImagePath); DPRINT("Type: %lx\n", Type); - /* - * Create device node - */ - - /* Use IopRootDeviceNode for now */ - Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); - - if (!NT_SUCCESS(Status)) - { - DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status); - LoadParams->Status = Status; - (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); - return; - } - /* Get existing DriverObject pointer (in case the driver has already been loaded and initialized) */ Status = IopGetDriverObject( @@ -1916,23 +1898,29 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) if (!NT_SUCCESS(Status) && Status != STATUS_IMAGE_ALREADY_LOADED) { DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); - IopFreeDeviceNode(DeviceNode); LoadParams->Status = Status; (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); return; } - /* - * Set a service name for the device node - */ - - RtlCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer); - /* * Initialize the driver module if it's loaded for the first time */ if (Status != STATUS_IMAGE_ALREADY_LOADED) { + Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); + + if (!NT_SUCCESS(Status)) + { + DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status); + MmUnloadSystemImage(ModuleObject); + LoadParams->Status = Status; + (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); + return; + } + + IopDisplayLoadingMessage(&DeviceNode->ServiceName); + Status = IopInitializeDriverModule( DeviceNode, ModuleObject, @@ -1950,11 +1938,11 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); return; } + + /* Initialize and start device */ + IopInitializeDevice(DeviceNode, DriverObject); + Status = IopStartDevice(DeviceNode); } - - /* Initialize and start device */ - IopInitializeDevice(DeviceNode, DriverObject); - Status = IopStartDevice(DeviceNode); } else { @@ -1962,9 +1950,6 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) /* IopGetDriverObject references the DriverObject, so dereference it */ ObDereferenceObject(DriverObject); - - /* Free device node since driver loading failed */ - IopFreeDeviceNode(DeviceNode); } /* Pass status to the caller and signal the event */ diff --git a/ntoskrnl/kd/kdio.c b/ntoskrnl/kd/kdio.c index 5dc2ee39858..ee41ccbeaa3 100644 --- a/ntoskrnl/kd/kdio.c +++ b/ntoskrnl/kd/kdio.c @@ -10,6 +10,7 @@ /* INCLUDES ******************************************************************/ #include +#include #include /* GLOBALS *******************************************************************/ diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index 9f9d6c1d3bd..8e842f8169d 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -90,6 +90,10 @@ static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]); +#ifdef __ROS_CMAKE__ +static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]); +#endif + /* GLOBALS *******************************************************************/ static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */ @@ -135,6 +139,9 @@ static const struct { "sregs", "sregs", "Display status registers.", KdbpCmdRegs }, { "dregs", "dregs", "Display debug registers.", KdbpCmdRegs }, { "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame addr", KdbpCmdBackTrace }, +#ifdef __ROS_CMAKE__ + { "dt", "dt [mod] [type] [addr]", "Print a struct. Addr is optional.", KdbpCmdPrintStruct }, +#endif /* Flow control */ { NULL, NULL, "Flow control", NULL }, @@ -453,6 +460,142 @@ KdbpCmdEvalExpression( return TRUE; } +#ifdef __ROS_CMAKE__ + +/*!\brief Print a struct + */ +static VOID +KdbpPrintStructInternal +(PROSSYM_INFO Info, + PCHAR Indent, + BOOLEAN DoRead, + PVOID BaseAddress, + PROSSYM_AGGREGATE Aggregate) +{ + ULONG i; + ULONGLONG Result; + PROSSYM_AGGREGATE_MEMBER Member; + ULONG IndentLen = strlen(Indent); + ROSSYM_AGGREGATE MemberAggregate = { }; + + for (i = 0; i < Aggregate->NumElements; i++) { + Member = &Aggregate->Elements[i]; + KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : ""); + if (DoRead) { + if (!strcmp(Member->Type, "_UNICODE_STRING")) { + KdbpPrint("\"%wZ\"\n", ((PCHAR)BaseAddress) + Member->BaseOffset); + continue; + } else if (!strcmp(Member->Type, "PUNICODE_STRING")) { + KdbpPrint("\"%wZ\"\n", *(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset))); + continue; + } + switch (Member->Size) { + case 1: + case 2: + case 4: + case 8: { + Result = 0; + if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) { + if (Member->Bits) { + Result >>= Member->FirstBit; + Result &= ((1 << Member->Bits) - 1); + } + KdbpPrint(" %lx\n", Result); + } + else goto readfail; + break; + } + default: { + if (Member->Size < 8) { + if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) { + int j; + for (j = 0; j < Member->Size; j++) { + KdbpPrint(" %02x", (int)(Result & 0xff)); + Result >>= 8; + } + } else goto readfail; + } else { + KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset); + Indent[IndentLen] = ' '; + if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) { + KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate); + RosSymFreeAggregate(&MemberAggregate); + } + Indent[IndentLen] = 0; + KdbpPrint("%s}\n", Indent); + } break; + } + } + } else { + readfail: + if (Member->Size <= 8) { + KdbpPrint(" ??\n"); + } else { + KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset); + Indent[IndentLen] = ' '; + if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) { + KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate); + RosSymFreeAggregate(&MemberAggregate); + } + Indent[IndentLen] = 0; + KdbpPrint("%s}\n", Indent); + } + } + } +} + +PROSSYM_INFO KdbpSymFindCachedFile(PUNICODE_STRING ModName); + +static BOOLEAN +KdbpCmdPrintStruct( + ULONG Argc, + PCHAR Argv[]) +{ + int i; + ULONGLONG Result = 0; + PVOID BaseAddress = 0; + ROSSYM_AGGREGATE Aggregate = { }; + UNICODE_STRING ModName = { }; + ANSI_STRING AnsiName = { }; + CHAR Indent[100] = { }; + if (Argc < 3) goto end; + AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]); + AnsiName.Buffer = Argv[1]; + RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE); + PROSSYM_INFO Info = KdbpSymFindCachedFile(&ModName); + + if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) { + DPRINT1("Could not get aggregate\n"); + goto end; + } + + // Get an argument for location if it was given + if (Argc > 3) { + ULONG len; + PCHAR ArgStart = Argv[3]; + DPRINT1("Trying to get expression\n"); + for (i = 3; i < Argc - 1; i++) + { + len = strlen(Argv[i]); + Argv[i][len] = ' '; + } + + /* Evaluate the expression */ + DPRINT1("Arg: %s\n", ArgStart); + if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result)) { + BaseAddress = (PVOID)(ULONG_PTR)Result; + DPRINT1("BaseAddress: %p\n", BaseAddress); + } + } + DPRINT1("BaseAddress %p\n", BaseAddress); + KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate); +end: + RosSymFreeAggregate(&Aggregate); + RtlFreeUnicodeString(&ModName); + return TRUE; +} +#endif + /*!\brief Display list of active debug channels */ static BOOLEAN diff --git a/ntoskrnl/kdbg/kdb_symbols.cmake.c b/ntoskrnl/kdbg/kdb_symbols.cmake.c index 2d43732b20f..e530cd9d6d8 100644 --- a/ntoskrnl/kdbg/kdb_symbols.cmake.c +++ b/ntoskrnl/kdbg/kdb_symbols.cmake.c @@ -199,8 +199,11 @@ KdbSymPrintAddress( if (Context) { +#if 0 + // Disable arguments for now DPRINT("Has Context %x (EBP %x)\n", Context, Context->Ebp); LineInfo.Flags = ROSSYM_LINEINFO_HAS_REGISTERS; +#endif for (i = 0; i < sizeof(regmap) / sizeof(regmap[0]); i++) { memcpy @@ -224,7 +227,7 @@ KdbSymPrintAddress( { DbgPrint("<%wZ:%x (%s:%d (%s))>", &LdrEntry->BaseDllName, RelativeAddress, LineInfo.FileName, LineInfo.LineNumber, LineInfo.FunctionName); - if (Context) + if (Context && LineInfo.NumParams) { int i; char *comma = ""; @@ -249,8 +252,10 @@ KdbSymPrintAddress( { goto end; } + SectionObject = MemoryArea->Data.SectionData.Section; if (!(SectionObject->AllocationAttributes & SEC_IMAGE)) goto end; +#if 0 if (MemoryArea->StartingAddress != (PVOID)KdbpImageBase) { if (KdbpRosSymInfo) @@ -287,7 +292,7 @@ KdbSymPrintAddress( LineInfo.LineNumber, LineInfo.FunctionName); - if (Context) + if (Context && LineInfo.NumParams) { int i; char *comma = ""; @@ -306,6 +311,7 @@ KdbSymPrintAddress( return TRUE; } } +#endif } end: @@ -359,7 +365,7 @@ KdbSymGetAddressInformation( * * \sa KdbpSymAddCachedFile */ -static PROSSYM_INFO +PROSSYM_INFO KdbpSymFindCachedFile( IN PUNICODE_STRING FileName) { @@ -405,7 +411,7 @@ KdbpSymAddCachedFile( { PIMAGE_SYMBOL_INFO_CACHE CacheEntry; - DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo); + DPRINT("Adding symbol file: %wZ RosSymInfo = %p\n", FileName, RosSymInfo); /* allocate entry */ CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS); @@ -416,6 +422,7 @@ KdbpSymAddCachedFile( CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, FileName->Length, TAG_KDBS); + CacheEntry->FileName.MaximumLength = FileName->Length; RtlCopyUnicodeString(&CacheEntry->FileName, FileName); ASSERT(CacheEntry->FileName.Buffer); CacheEntry->RefCount = 1; @@ -476,7 +483,7 @@ KdbpSymRemoveCachedFile( * * \sa KdbpSymUnloadModuleSymbols */ -static VOID +VOID KdbpSymLoadModuleSymbols( IN PUNICODE_STRING FileName, OUT PROSSYM_INFO *RosSymInfo) @@ -508,7 +515,7 @@ KdbpSymLoadModuleSymbols( /* Open the file */ InitializeObjectAttributes(&ObjectAttributes, FileName, - OBJ_CASE_INSENSITIVE, + OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL); @@ -519,10 +526,10 @@ KdbpSymLoadModuleSymbols( &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_SYNCHRONOUS_IO_NONALERT); + FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { - DPRINT("Could not open image file: %wZ\n", FileName); + DPRINT("Could not open image file(%x): %wZ\n", Status, FileName); return; } @@ -548,8 +555,17 @@ KdbpSymLoadModuleSymbols( if (RosSymCreateFromFile(FileContext, RosSymInfo)) { /* add file to cache */ - KdbpSymAddCachedFile(FileName, *RosSymInfo); - DPRINT("Installed symbols: %wZ %p\n", FileName, *RosSymInfo); + int i; + UNICODE_STRING TruncatedName = *FileName; + for (i = (TruncatedName.Length / sizeof(WCHAR)) - 1; i >= 0; i--) + if (TruncatedName.Buffer[i] == '\\') { + TruncatedName.Buffer += i+1; + TruncatedName.Length -= (i+1)*sizeof(WCHAR); + TruncatedName.MaximumLength -= (i+1)*sizeof(WCHAR); + break; + } + KdbpSymAddCachedFile(&TruncatedName, *RosSymInfo); + DPRINT("Installed symbols: %wZ %p\n", &TruncatedName, *RosSymInfo); } KdbpReleaseFileForSymbols(FileContext); } @@ -569,13 +585,45 @@ KdbSymProcessSymbols( } /* Remove symbol info if it already exists */ - if (LdrEntry->PatchInformation) + if (LdrEntry->PatchInformation) { KdbpSymRemoveCachedFile(LdrEntry->PatchInformation); + } /* Error loading symbol info, try to load it from file */ KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName, (PROSSYM_INFO*)&LdrEntry->PatchInformation); + if (!LdrEntry->PatchInformation) { + // HACK: module dll names don't identify the real files + UNICODE_STRING SystemRoot; + UNICODE_STRING ModuleNameCopy; + RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot\\system32\\Drivers\\"); + ModuleNameCopy.Length = 0; + ModuleNameCopy.MaximumLength = + LdrEntry->BaseDllName.MaximumLength + SystemRoot.MaximumLength; + ModuleNameCopy.Buffer = ExAllocatePool(NonPagedPool, SystemRoot.MaximumLength + LdrEntry->BaseDllName.MaximumLength); + RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot); + RtlCopyMemory + (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR), + LdrEntry->BaseDllName.Buffer, + LdrEntry->BaseDllName.Length); + ModuleNameCopy.Length += LdrEntry->BaseDllName.Length; + KdbpSymLoadModuleSymbols(&ModuleNameCopy, + (PROSSYM_INFO*)&LdrEntry->PatchInformation); + if (!LdrEntry->PatchInformation) { + SystemRoot.Length -= strlen("Drivers\\") * sizeof(WCHAR); + RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot); + RtlCopyMemory + (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR), + LdrEntry->BaseDllName.Buffer, + LdrEntry->BaseDllName.Length); + ModuleNameCopy.Length += LdrEntry->BaseDllName.Length; + KdbpSymLoadModuleSymbols(&ModuleNameCopy, + (PROSSYM_INFO*)&LdrEntry->PatchInformation); + } + RtlFreeUnicodeString(&ModuleNameCopy); + } + /* It already added symbols to cache */ DPRINT("Installed symbols: %wZ@%p-%p %p\n", &LdrEntry->BaseDllName, diff --git a/ntoskrnl/ke/arm/cpu.c b/ntoskrnl/ke/arm/cpu.c index 37d8a1569fd..5b458517cf1 100644 --- a/ntoskrnl/ke/arm/cpu.c +++ b/ntoskrnl/ke/arm/cpu.c @@ -90,23 +90,6 @@ KeInvalidateAllCaches(VOID) return TRUE; } -BOOLEAN -NTAPI -KeDisableInterrupts(VOID) -{ - ARM_STATUS_REGISTER Flags; - - // - // Get current interrupt state and disable interrupts - // - Flags = KeArmStatusRegisterGet(); - _disable(); - - // - // Return previous interrupt state - // - return Flags.IrqDisable; -} /* PUBLIC FUNCTIONS ***********************************************************/ @@ -130,17 +113,17 @@ KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors) { KIRQL OldIrql; - + // // Raise the IRQL for the TB Flush // OldIrql = KeRaiseIrqlToSynchLevel(); - + // // Flush the TB for the Current CPU // KeFlushCurrentTb(); - + // // Return to Original IRQL // @@ -168,7 +151,7 @@ NTAPI KeQueryActiveProcessors(VOID) { PAGED_CODE(); - + // // Simply return the number of active processors // @@ -186,7 +169,7 @@ KeSaveStateForHibernate(IN PKPROCESSOR_STATE State) // Capture the context // RtlCaptureContext(&State->ContextFrame); - + // // Capture the control state // diff --git a/ntoskrnl/ke/i386/cpu.c b/ntoskrnl/ke/i386/cpu.c index 0fd2dcc459d..74c1043fe0a 100644 --- a/ntoskrnl/ke/i386/cpu.c +++ b/ntoskrnl/ke/i386/cpu.c @@ -1173,22 +1173,6 @@ KiI386PentiumLockErrataFixup(VOID) MmSetPageProtect(NULL, NewIdt, PAGE_READONLY); } -BOOLEAN -NTAPI -KeDisableInterrupts(VOID) -{ - ULONG Flags; - BOOLEAN Return; - - /* Get EFLAGS and check if the interrupt bit is set */ - Flags = __readeflags(); - Return = (Flags & EFLAGS_INTERRUPT_MASK) ? TRUE: FALSE; - - /* Disable interrupts */ - _disable(); - return Return; -} - BOOLEAN NTAPI KeInvalidateAllCaches(VOID) diff --git a/ntoskrnl/ke/i386/exp.c b/ntoskrnl/ke/i386/exp.c index 6ef92e0b91f..2aa53f655a5 100644 --- a/ntoskrnl/ke/i386/exp.c +++ b/ntoskrnl/ke/i386/exp.c @@ -611,7 +611,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, if (PreviousMode != KernelMode) { /* Save the mask */ - KeGetCurrentThread()->DispatcherHeader.DebugActive = DrMask; + KeGetCurrentThread()->DispatcherHeader.DebugActive = (DrMask != 0); } } diff --git a/ntoskrnl/ke/i386/trap.s b/ntoskrnl/ke/i386/trap.s index 73d1cbcf71d..8d7a809c6c5 100644 --- a/ntoskrnl/ke/i386/trap.s +++ b/ntoskrnl/ke/i386/trap.s @@ -32,6 +32,8 @@ EXTERN _KiTrap02:PROC .data ASSUME nothing +.align 16 + PUBLIC _KiIdt _KiIdt: /* This is the Software Interrupt Table that we handle in this file: */ @@ -124,15 +126,19 @@ _KiInterruptTemplateDispatch: EXTERN @KiSystemServiceHandler@8:PROC PUBLIC _KiSystemService -_KiSystemService: +.PROC KiSystemService + FPO 0, 0, 0, 0, 1, FRAME_TRAP KiEnterTrap (KI_PUSH_FAKE_ERROR_CODE OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS) KiCallHandler @KiSystemServiceHandler@8 +.ENDP KiSystemService EXTERN @KiFastCallEntryHandler@8:PROC PUBLIC _KiFastCallEntry -_KiFastCallEntry: +.PROC KiFastCallEntry + FPO 0, 0, 0, 0, 1, FRAME_TRAP KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS) KiCallHandler @KiFastCallEntryHandler@8 +.ENDP KiFastCallEntry PUBLIC _KiStartUnexpectedRange@0 _KiStartUnexpectedRange@0: @@ -161,6 +167,9 @@ EXTERN _PsConvertToGuiThread@0:PROC PUBLIC _KiConvertToGuiThread@0 _KiConvertToGuiThread@0: + /* Safe ebx */ + push ebx + /* Calculate the stack frame offset in ebx */ mov ebx, ebp sub ebx, esp @@ -172,6 +181,9 @@ _KiConvertToGuiThread@0: mov ebp, esp add ebp, ebx + /* Restore ebx */ + pop ebx + /* return to the caller */ ret #endif diff --git a/ntoskrnl/ke/i386/traphdlr.c b/ntoskrnl/ke/i386/traphdlr.c index 1f5cd46bf4b..e733cba8519 100644 --- a/ntoskrnl/ke/i386/traphdlr.c +++ b/ntoskrnl/ke/i386/traphdlr.c @@ -1199,6 +1199,35 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame) #endif } + /* Check for S-LIST fault in kernel mode */ + if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) + { + PSLIST_HEADER SListHeader; + + /* Sanity check that the assembly is correct: + This must be mov ebx, [eax] + Followed by cmpxchg8b [ebp] */ + ASSERT((((UCHAR*)TrapFrame->Eip)[0] == 0x8B) && + (((UCHAR*)TrapFrame->Eip)[1] == 0x18) && + (((UCHAR*)TrapFrame->Eip)[2] == 0x0F) && + (((UCHAR*)TrapFrame->Eip)[3] == 0xC7) && + (((UCHAR*)TrapFrame->Eip)[4] == 0x4D) && + (((UCHAR*)TrapFrame->Eip)[5] == 0x00)); + + /* Get the pointer to the SLIST_HEADER */ + SListHeader = (PSLIST_HEADER)TrapFrame->Ebp; + + /* Check if the Next member of the SLIST_HEADER was changed */ + if (SListHeader->Next.Next != (PSLIST_ENTRY)TrapFrame->Eax) + { + /* Restart the operation */ + TrapFrame->Eip = (ULONG_PTR)ExpInterlockedPopEntrySListResume; + + /* Continue execution */ + KiEoiHelper(TrapFrame); + } + } + /* Call the access fault handler */ Status = MmAccessFault(TrapFrame->ErrCode & 1, (PVOID)Cr2, @@ -1206,14 +1235,6 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame) TrapFrame); if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame); - /* Check for S-LIST fault */ - if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) - { - /* Not yet implemented */ - UNIMPLEMENTED; - while (TRUE); - } - /* Check for syscall fault */ #if 0 if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) || diff --git a/ntoskrnl/ke/i386/usercall.c b/ntoskrnl/ke/i386/usercall.c index 07ce4442df4..9363c6fed5f 100644 --- a/ntoskrnl/ke/i386/usercall.c +++ b/ntoskrnl/ke/i386/usercall.c @@ -4,6 +4,7 @@ * FILE: ntoskrnl/ke/i386/usercall.c * PURPOSE: User-mode Callout Mechanisms (APC and Win32K Callbacks) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Timo Kreuzer (timo.kreuzer@reactos.org) */ /* INCLUDES ******************************************************************/ @@ -208,4 +209,147 @@ KeUserModeCallback(IN ULONG RoutineIndex, return CallbackStatus; } + +/* + * Stack layout for KiUserModeCallout: + * ---------------------------------- + * KCALLOUT_FRAME.ResultLength <= 2nd Parameter to KiCallUserMode + * KCALLOUT_FRAME.Result <= 1st Parameter to KiCallUserMode + * KCALLOUT_FRAME.ReturnAddress <= Return address of KiCallUserMode + * KCALLOUT_FRAME.Ebp \ + * KCALLOUT_FRAME.Ebx | = non-volatile registers, pushed + * KCALLOUT_FRAME.Esi | by KiCallUserMode + * KCALLOUT_FRAME.Edi / + * KCALLOUT_FRAME.CallbackStack + * KCALLOUT_FRAME.TrapFrame + * KCALLOUT_FRAME.InitialStack <= CalloutFrame points here + * ---------------------------------- + * ~~ optional alignment ~~ + * ---------------------------------- + * FX_SAVE_AREA + * ---------------------------------- + * KTRAP_FRAME + * ---------------------------------- + * ~~ begin of stack frame for KiUserModeCallout ~~ + * + */ + +NTSTATUS +FASTCALL +KiUserModeCallout(PKCALLOUT_FRAME CalloutFrame) +{ + PKTHREAD CurrentThread; + PKTRAP_FRAME TrapFrame, CallbackTrapFrame; + PFX_SAVE_AREA FxSaveArea, OldFxSaveArea; + PKPCR Pcr; + PKTSS Tss; + ULONG_PTR InitialStack; + NTSTATUS Status; + + /* Get the current thread */ + CurrentThread = KeGetCurrentThread(); + +#if DBG + /* Check if we are at pasive level */ + if (KeGetCurrentIrql() != PASSIVE_LEVEL) + { + /* We're not, bugcheck */ + KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE, + 0, + KeGetCurrentIrql(), + 0, + 0); + } + + /* Check if we are attached or APCs are disabled */ + if ((CurrentThread->ApcStateIndex != OriginalApcEnvironment) || + (CurrentThread->CombinedApcDisable > 0)) + { + KeBugCheckEx(APC_INDEX_MISMATCH, + 0, + CurrentThread->ApcStateIndex, + CurrentThread->CombinedApcDisable, + 0); + } +#endif + + /* Align stack on a 16-byte boundary */ + InitialStack = ALIGN_DOWN_BY(CalloutFrame, 16); + + /* Check if we have enough space on the stack */ + if ((InitialStack - KERNEL_STACK_SIZE) < CurrentThread->StackLimit) + { + /* We don't, we'll have to grow our stack */ + Status = MmGrowKernelStack((PVOID)InitialStack); + + /* Quit if we failed */ + if (!NT_SUCCESS(Status)) return Status; + } + + /* Save the current callback stack and initial stack */ + CalloutFrame->CallbackStack = (ULONG_PTR)CurrentThread->CallbackStack; + CalloutFrame->InitialStack = (ULONG_PTR)CurrentThread->InitialStack; + + /* Get and save the trap frame */ + TrapFrame = CurrentThread->TrapFrame; + CalloutFrame->TrapFrame = (ULONG_PTR)TrapFrame; + + /* Set the new callback stack */ + CurrentThread->CallbackStack = CalloutFrame; + + /* Set destination and origin NPX Areas */ + OldFxSaveArea = (PVOID)(CalloutFrame->InitialStack - sizeof(FX_SAVE_AREA)); + FxSaveArea = (PVOID)(InitialStack - sizeof(FX_SAVE_AREA)); + + /* Disable interrupts so we can fill the NPX State */ + _disable(); + + /* Now copy the NPX State */ + FxSaveArea->U.FnArea.ControlWord = OldFxSaveArea->U.FnArea.ControlWord; + FxSaveArea->U.FnArea.StatusWord = OldFxSaveArea->U.FnArea.StatusWord; + FxSaveArea->U.FnArea.TagWord = OldFxSaveArea->U.FnArea.TagWord; + FxSaveArea->U.FnArea.DataSelector = OldFxSaveArea->U.FnArea.DataSelector; + FxSaveArea->Cr0NpxState = OldFxSaveArea->Cr0NpxState; + + /* Set the stack address */ + CurrentThread->InitialStack = (PVOID)InitialStack; + + /* Locate the trap frame on the callback stack */ + CallbackTrapFrame = (PVOID)((ULONG_PTR)FxSaveArea - sizeof(KTRAP_FRAME)); + + /* Copy the trap frame to the new location */ + *CallbackTrapFrame = *TrapFrame; + + /* Get PCR */ + Pcr = KeGetPcr(); + + /* Update the exception list */ + CallbackTrapFrame->ExceptionList = Pcr->NtTib.ExceptionList; + + /* Get TSS */ + Tss = Pcr->TSS; + + /* Check for V86 mode */ + if (CallbackTrapFrame->EFlags & EFLAGS_V86_MASK) + { + /* Set new stack address in TSS (full trap frame) */ + Tss->Esp0 = (ULONG_PTR)(CallbackTrapFrame + 1); + } + else + { + /* Set new stack address in TSS (non-V86 trap frame) */ + Tss->Esp0 = (ULONG_PTR)&CallbackTrapFrame->V86Es; + } + + /* Set user-mode dispatcher address as EIP */ + CallbackTrapFrame->Eip = (ULONG_PTR)KeUserCallbackDispatcher; + + /* Bring interrupts back */ + _enable(); + + /* Exit to user-mode */ + KiServiceExit(CallbackTrapFrame, 0); +} + + /* EOF */ diff --git a/ntoskrnl/ke/i386/usercall_asm.S b/ntoskrnl/ke/i386/usercall_asm.S index 341cefd9bee..62078c92d86 100644 --- a/ntoskrnl/ke/i386/usercall_asm.S +++ b/ntoskrnl/ke/i386/usercall_asm.S @@ -17,20 +17,11 @@ EXTERN _KeUserCallbackDispatcher:DWORD EXTERN @KiServiceExit@8:PROC EXTERN _KeGetCurrentIrql@0:PROC EXTERN _KeBugCheckEx@20:PROC +EXTERN @KiUserModeCallout@4:PROC /* FUNCTIONS ****************************************************************/ .code -PUBLIC _KiGetUserModeStackAddress@0 -_KiGetUserModeStackAddress@0: - - /* Get the current thread's trapframe and return the esp */ - mov eax, fs:[KPCR_CURRENT_THREAD] - mov eax, [eax+KTHREAD_TRAP_FRAME] - lea eax, [eax+KTRAP_FRAME_ESP] - ret - - /*++ * @name KiCallUserMode * @@ -58,166 +49,23 @@ _KiGetUserModeStackAddress@0: PUBLIC _KiCallUserMode@8 _KiCallUserMode@8: - /* Save volatile registers */ + /* Push non-volatile registers on the stack. + This is part of the KCALLOUT_FRAME */ push ebp push ebx push esi push edi - /* Get the current thread */ - mov ebx, fs:[KPCR_CURRENT_THREAD] - - /* Make sure we're at passive */ -#if DBG - call _KeGetCurrentIrql@0 - or al, al - jz AtPassive - - /* We're not, bugcheck! */ - push 0 - push 0 - push eax - push 0 - push IRQL_GT_ZERO_AT_SYSTEM_SERVICE - call _KeBugCheckEx@20 - -AtPassive: - - /* Make sure that we are not attached and that APCs are not disabled */ - movzx eax, byte ptr [ebx+KTHREAD_APC_STATE_INDEX] - mov edx, [ebx+KTHREAD_COMBINED_APC_DISABLE] - or eax, eax - jnz InvalidIndex - or edx, edx - jz ApcsEnabled - -InvalidIndex: - - push 0 - push edx - push eax - push 0 - push APC_INDEX_MISMATCH - call _KeBugCheckEx@20 -ApcsEnabled: -#endif - - /* Get the lowest stack limit and check if we can handle it */ - lea eax, [esp-HEX(3000)] - cmp eax, [ebx+KTHREAD_STACK_LIMIT] - jnb StackOk - - /* We can't, we'll have to grow our stack */ - push esp - call _MmGrowKernelStack@4 - - /* Quit if we failed */ - or eax, eax - jnz GrowFailed - - /* Save the current callback stack */ -StackOk: - push [ebx+KTHREAD_CALLBACK_STACK] - - /* Get and save the trap frame */ - mov edx, [ebx+KTHREAD_TRAP_FRAME] - push edx - - /* Get and save the initial stack */ - mov esi, [ebx+KTHREAD_INITIAL_STACK] - push esi - - /* Set the new callback stack */ - mov [ebx+KTHREAD_CALLBACK_STACK], esp - - /* Align stack on 16-byte boundary */ - and esp, NOT 15 - mov edi, esp - - /* Set destination and origin NPX Areas */ - sub esp, NPX_FRAME_LENGTH - sub esi, NPX_FRAME_LENGTH - - /* Disable interrupts so we can fill the NPX State */ - cli - - /* Now copy the NPX State */ - mov ecx, [esi+FP_CONTROL_WORD] - mov [esp+FP_CONTROL_WORD], ecx - mov ecx, [esi+FP_STATUS_WORD] - mov [esp+FP_STATUS_WORD], ecx - mov ecx, [esi+FP_TAG_WORD] - mov [esp+FP_TAG_WORD], ecx - mov ecx, [esi+FP_DATA_SELECTOR] - mov [esp+FP_DATA_SELECTOR], ecx - mov ecx, [esi+FN_CR0_NPX_STATE] - mov [esp+FN_CR0_NPX_STATE], ecx - - /* Get TSS */ - mov esi, fs:[KPCR_TSS] - - /* Set the stack address */ - mov [ebx+KTHREAD_INITIAL_STACK], edi + /* load the address of the callout frame into ecx */ + lea ecx, [esp - 12] - /* Bias the stack for V86 mode */ - mov ecx, esp - sub esp, 16 - test dword ptr [edx+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jnz DontBias - mov ecx, esp + /* Allocate space for the inital stack */ + sub esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16 -DontBias: - /* Set new stack address in TSS */ - mov [esi+KTSS_ESP0], ecx + call @KiUserModeCallout@4 - /* Allocate the trap frame and set it */ - sub esp, KTRAP_FRAME_V86_ES - mov ebp, esp - - /* Set copy iterator and dest/origin parameters and do the copy */ - mov ecx, (KTRAP_FRAME_V86_ES - KTRAP_FRAME_FS) / 4 - lea edi, [esp+KTRAP_FRAME_FS] - lea esi, [edx+KTRAP_FRAME_FS] - rep movsd - - /* Copy DR7 */ - mov edi, [edx+KTRAP_FRAME_DR7] - test edi, NOT DR7_RESERVED_MASK - mov [esp+KTRAP_FRAME_DR7], edi - - /* Check if we need to save debug registers */ - jnz SaveDebug - - /* Get user-mode dispatcher address and set it as EIP */ -SetEip: - mov eax, dword ptr [_KeUserCallbackDispatcher] - mov [esp+KTRAP_FRAME_EIP], eax - - /* Set the exception list */ - mov eax, fs:[KPCR_EXCEPTION_LIST] - mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax - - /* Set the previous mode */ - mov eax, [edx+KTRAP_FRAME_PREVIOUS_MODE] - mov [esp+KTRAP_FRAME_PREVIOUS_MODE], eax - - /* Bring interrupts back */ - sti - - /* Exit to user-mode */ - mov ecx, esp - jmp @KiServiceExit@8 - -SaveDebug: - - /* Copy all 5 DRs */ - mov ecx, 5 - lea edi, [esp+KTRAP_FRAME_DR0] - lea esi, [edx+KTRAP_FRAME_DR0] - rep movsd - jmp SetEip + add esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16 -GrowFailed: /* Restore registers */ pop edi pop esi diff --git a/ntoskrnl/lpc/complete.c b/ntoskrnl/lpc/complete.c index 67de3871976..1ef57631b62 100644 --- a/ntoskrnl/lpc/complete.c +++ b/ntoskrnl/lpc/complete.c @@ -148,7 +148,11 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle, RtlCopyMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength); /* At this point, if the caller refused the connection, go to cleanup */ - if (!AcceptConnection) goto Cleanup; + if (!AcceptConnection) + { + DPRINT1("LPC connection was refused\n"); + goto Cleanup; + } /* Otherwise, create the actual port */ Status = ObCreateObject(PreviousMode, @@ -222,6 +226,11 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle, { /* Otherwise, quit */ ObDereferenceObject(ServerPort); + DPRINT1("Client section mapping failed: %lx\n", Status); + DPRINT1("View base, offset, size: %lx %lx %lx\n", + ServerPort->ClientSectionBase, + ConnectMessage->ClientView.ViewSize, + SectionOffset); goto Cleanup; } } diff --git a/ntoskrnl/mm/ARM3/mmdbg.c b/ntoskrnl/mm/ARM3/mmdbg.c index 8d80e174f4d..1029fdf8e0f 100644 --- a/ntoskrnl/mm/ARM3/mmdbg.c +++ b/ntoskrnl/mm/ARM3/mmdbg.c @@ -150,6 +150,8 @@ MmDbgCopyMemory(IN ULONG64 Address, { NTSTATUS Status; PVOID TargetAddress; + ULONG64 PhysicalAddress; + PMMPTE PointerPte; // // No local kernel debugging support yet, so don't worry about locking @@ -238,34 +240,30 @@ MmDbgCopyMemory(IN ULONG64 Address, // No session space support yet // ASSERT(MmIsSessionAddress(TargetAddress) == FALSE); - } - // - // If we are going to write to the address then make sure it is writeable too - // - if ((Flags & MMDBG_COPY_WRITE) && - (!MI_IS_PAGE_WRITEABLE(MiAddressToPte(TargetAddress)))) - { - // - // Check if we mapped anything - // - if (Flags & MMDBG_COPY_PHYSICAL) + /* If we are going to write to the address, then check if its writable */ + PointerPte = MiAddressToPte(TargetAddress); + if ((Flags & MMDBG_COPY_WRITE) && !MI_IS_PAGE_WRITEABLE(PointerPte)) { - // - // Get rid of the mapping - // - MiDbgUnTranslatePhysicalAddress(); + /* Not writable, we need to do a physical copy */ + Flags |= MMDBG_COPY_PHYSICAL; + + /* Calculate the physical address */ + PhysicalAddress = PointerPte->u.Hard.PageFrameNumber << PAGE_SHIFT; + PhysicalAddress += BYTE_OFFSET(Address); + + /* Translate the physical address */ + TargetAddress = MiDbgTranslatePhysicalAddress(PhysicalAddress, Flags); + + /* Check if translation failed */ + if (!TargetAddress) + { + /* Fail */ + KdpDprintf("MmDbgCopyMemory: Failed to translate for write " + "%I64x (%I64x)\n", PhysicalAddress, Address); + return STATUS_UNSUCCESSFUL; + } } - - // - // Fail - // - // FIXME: We should attempt to override the write protection instead of - // failing here - // - KdpDprintf("MmDbgCopyMemory: Failing Write for Protected Address 0x%p\n", - TargetAddress); - return STATUS_UNSUCCESSFUL; } // diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index f40e5171256..79612f17b31 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -576,13 +576,7 @@ MmCreatePeb(IN PEPROCESS Process, // Attach to Process // KeAttachProcess(&Process->Pcb); - - // - // Allocate the PEB - // - Status = MiCreatePebOrTeb(Process, sizeof(PEB), (PULONG_PTR)&Peb); - ASSERT(NT_SUCCESS(Status)); - + // // Map NLS Tables // @@ -596,7 +590,25 @@ MmCreatePeb(IN PEPROCESS Process, ViewShare, MEM_TOP_DOWN, PAGE_READONLY); - if (!NT_SUCCESS(Status)) return Status; + DPRINT1("NLS Tables at: %p\n", TableBase); + if (!NT_SUCCESS(Status)) + { + /* Cleanup and exit */ + KeDetachProcess(); + return Status; + } + + // + // Allocate the PEB + // + Status = MiCreatePebOrTeb(Process, sizeof(PEB), (PULONG_PTR)&Peb); + DPRINT1("PEB at: %p\n", Peb); + if (!NT_SUCCESS(Status)) + { + /* Cleanup and exit */ + KeDetachProcess(); + return Status; + } // // Use SEH in case we can't load the PEB @@ -636,7 +648,7 @@ MmCreatePeb(IN PEPROCESS Process, // Heap and Debug Data // Peb->NumberOfProcessors = KeNumberProcessors; - Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL ? TRUE : FALSE); + Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL); Peb->NtGlobalFlag = NtGlobalFlag; /*Peb->HeapSegmentReserve = MmHeapSegmentReserve; Peb->HeapSegmentCommit = MmHeapSegmentCommit; @@ -730,34 +742,20 @@ MmCreatePeb(IN PEPROCESS Process, Peb->OSMinorVersion = (NtHeaders->OptionalHeader.Win32VersionValue >> 8) & 0xFF; Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF; Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2; - } - // - // Process the image config data overrides if specfied - // - if (ImageConfigData != NULL) - { - // - // Process CSD version override - // - if (ImageConfigData->CSDVersion) + /* Process CSD version override */ + if ((ImageConfigData) && (ImageConfigData->CSDVersion)) { - // - // Set new data - // + /* Take the value from the image configuration directory */ Peb->OSCSDVersion = ImageConfigData->CSDVersion; } + } - // - // Process affinity mask ovverride - // - if (ImageConfigData->ProcessAffinityMask) - { - // - // Set new data - // - ProcessAffinityMask = ImageConfigData->ProcessAffinityMask; - } + /* Process optional process affinity mask override */ + if ((ImageConfigData) && (ImageConfigData->ProcessAffinityMask)) + { + /* Take the value from the image configuration directory */ + ProcessAffinityMask = ImageConfigData->ProcessAffinityMask; } // @@ -767,6 +765,7 @@ MmCreatePeb(IN PEPROCESS Process, // // Force it to use CPU 0 // + /* FIXME: this should use the MmRotatingUniprocessorNumber */ Peb->ImageProcessAffinityMask = 0; } else diff --git a/ntoskrnl/mm/ARM3/vadnode.c b/ntoskrnl/mm/ARM3/vadnode.c index 551a1946f8e..a3aac247bea 100644 --- a/ntoskrnl/mm/ARM3/vadnode.c +++ b/ntoskrnl/mm/ARM3/vadnode.c @@ -396,8 +396,7 @@ MiFindEmptyAddressRangeDownTree(IN SIZE_T Length, /* Starting from the root, go down until the right-most child, trying to stay below the boundary. */ LowestNode = Node = RtlRightChildAvl(&Table->BalancedRoot); - while ( (Child = RtlRightChildAvl(Node)) && - Child->EndingVpn < HighVpn ) Node = Child; + while ((Child = RtlRightChildAvl(Node))) Node = Child; /* Now loop the Vad nodes */ while (Node) diff --git a/ntoskrnl/mm/anonmem.c b/ntoskrnl/mm/anonmem.c index 766a8fc17c2..70211e5fb72 100644 --- a/ntoskrnl/mm/anonmem.c +++ b/ntoskrnl/mm/anonmem.c @@ -48,89 +48,6 @@ /* FUNCTIONS *****************************************************************/ -NTSTATUS -NTAPI -MmWritePageVirtualMemory(PMMSUPPORT AddressSpace, - PMEMORY_AREA MemoryArea, - PVOID Address, - PMM_PAGEOP PageOp) -{ - SWAPENTRY SwapEntry; - PFN_NUMBER Page; - NTSTATUS Status; - PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); - - /* - * Check for paging out from a deleted virtual memory area. - */ - if (MemoryArea->DeleteInProgress) - { - PageOp->Status = STATUS_UNSUCCESSFUL; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_UNSUCCESSFUL); - } - - Page = MmGetPfnForProcess(Process, Address); - - /* - * Get that the page actually is dirty. - */ - if (!MmIsDirtyPage(Process, Address)) - { - PageOp->Status = STATUS_SUCCESS; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_SUCCESS); - } - - /* - * Speculatively set the mapping to clean. - */ - MmSetCleanPage(Process, Address); - - /* - * If necessary, allocate an entry in the paging file for this page - */ - SwapEntry = MmGetSavedSwapEntryPage(Page); - if (SwapEntry == 0) - { - SwapEntry = MmAllocSwapPage(); - if (SwapEntry == 0) - { - MmSetDirtyPage(Process, Address); - PageOp->Status = STATUS_PAGEFILE_QUOTA_EXCEEDED; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_PAGEFILE_QUOTA_EXCEEDED); - } - } - - /* - * Write the page to the pagefile - */ - Status = MmWriteToSwapPage(SwapEntry, Page); - if (!NT_SUCCESS(Status)) - { - DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", - Status); - MmSetDirtyPage(Process, Address); - PageOp->Status = STATUS_UNSUCCESSFUL; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_UNSUCCESSFUL); - } - - /* - * Otherwise we have succeeded. - */ - MmSetSavedSwapEntryPage(Page, SwapEntry); - PageOp->Status = STATUS_SUCCESS; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_SUCCESS); -} - NTSTATUS NTAPI MmPageOutVirtualMemory(PMMSUPPORT AddressSpace, diff --git a/ntoskrnl/mm/freelist.c b/ntoskrnl/mm/freelist.c index 7eef9593f95..b9097511cd8 100644 --- a/ntoskrnl/mm/freelist.c +++ b/ntoskrnl/mm/freelist.c @@ -33,7 +33,6 @@ PFN_NUMBER MmAvailablePages; PFN_NUMBER MmResidentAvailablePages; PFN_NUMBER MmResidentAvailableAtInit; -SIZE_T MmTotalCommitLimit; SIZE_T MmTotalCommittedPages; SIZE_T MmSharedCommit; SIZE_T MmDriverCommit; diff --git a/ntoskrnl/mm/region.c b/ntoskrnl/mm/region.c index 9c79738b036..413d96bc6b3 100644 --- a/ntoskrnl/mm/region.c +++ b/ntoskrnl/mm/region.c @@ -53,7 +53,7 @@ MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress, TAG_MM_REGION); if (NewRegion1 == NULL) { - ExFreePool(NewRegion2); + ExFreePoolWithTag(NewRegion2, TAG_MM_REGION); return(NULL); } NewRegion1->Type = NewType; @@ -86,14 +86,14 @@ MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress, } else { - ExFreePool(NewRegion2); + ExFreePoolWithTag(NewRegion2, TAG_MM_REGION); } /* Either remove or shrink the initial region. */ if (InitialBaseAddress == StartAddress) { RemoveEntryList(&InitialRegion->RegionListEntry); - ExFreePool(InitialRegion); + ExFreePoolWithTag(InitialRegion, TAG_MM_REGION); } else { @@ -123,17 +123,6 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, */ InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress, &InitialBaseAddress); - if (((char*)StartAddress + Length) > - ((char*)InitialBaseAddress + InitialRegion->Length)) - { - RemainingLength = ((char*)StartAddress + Length) - - ((char*)InitialBaseAddress + InitialRegion->Length); - } - else - { - RemainingLength = 0; - } - /* * If necessary then split the region into the affected and unaffected parts. */ @@ -146,10 +135,19 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, { return(STATUS_NO_MEMORY); } + if(NewRegion->Length < Length) + RemainingLength = Length - NewRegion->Length; + else + RemainingLength = 0; } else { NewRegion = InitialRegion; + if(((ULONG_PTR)InitialBaseAddress + NewRegion->Length) < + ((ULONG_PTR)StartAddress + Length)) + RemainingLength = ((ULONG_PTR)StartAddress + Length) - ((ULONG_PTR)InitialBaseAddress + NewRegion->Length); + else + RemainingLength = 0; } /* @@ -163,7 +161,7 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength && CurrentEntry != RegionListHead) { - if (CurrentRegion->Type != NewType && + if (CurrentRegion->Type != NewType || CurrentRegion->Protect != NewProtect) { AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length, @@ -176,7 +174,7 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, RemainingLength -= CurrentRegion->Length; CurrentEntry = CurrentEntry->Flink; RemoveEntryList(&CurrentRegion->RegionListEntry); - ExFreePool(CurrentRegion); + ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION); CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry); } @@ -188,10 +186,10 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, { CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry); - if (CurrentRegion->Type != NewType && + if (CurrentRegion->Type != NewType || CurrentRegion->Protect != NewProtect) { - AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length, + AlterFunc(AddressSpace, CurrentBaseAddress, RemainingLength, CurrentRegion->Type, CurrentRegion->Protect, NewType, NewProtect); } @@ -212,7 +210,7 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, { NewRegion->Length += CurrentRegion->Length; RemoveEntryList(&CurrentRegion->RegionListEntry); - ExFreePool(CurrentRegion); + ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION); } } @@ -229,7 +227,7 @@ MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress, { NewRegion->Length += CurrentRegion->Length; RemoveEntryList(&CurrentRegion->RegionListEntry); - ExFreePool(CurrentRegion); + ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION); } } diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 7749a03eb05..6948d47de18 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -124,8 +124,6 @@ MM_SECTION_PAGEOUT_CONTEXT; POBJECT_TYPE MmSectionObjectType = NULL; -SIZE_T MmAllocationFragment; - ULONG_PTR MmSubsectionBase; static ULONG SectionCharacteristicsToProtect[16] = diff --git a/ntoskrnl/ntoskrnl.spec b/ntoskrnl/ntoskrnl.spec index 021abac3809..d3ccb9b5279 100644 --- a/ntoskrnl/ntoskrnl.spec +++ b/ntoskrnl/ntoskrnl.spec @@ -178,7 +178,7 @@ @ fastcall -arch=i386 Exfi386InterlockedExchangeUlong(ptr long) @ fastcall -arch=i386 Exfi386InterlockedIncrementLong(ptr) @ stdcall -arch=i386 Exi386InterlockedDecrementLong(ptr) -@ stdcall -arch=i386 Exi386InterlockedExchangeUlong(ptr long long) +@ stdcall -arch=i386 Exi386InterlockedExchangeUlong(ptr long) @ stdcall -arch=i386 Exi386InterlockedIncrementLong(ptr) @ fastcall -arch=i386 ExiAcquireFastMutex(ptr) ExAcquireFastMutex @ fastcall -arch=i386 ExiReleaseFastMutex(ptr) ExReleaseFastMutex diff --git a/subsystems/win32/csrss/csrsrv/CMakeLists.txt b/subsystems/win32/csrss/csrsrv/CMakeLists.txt index 26989823cf9..6d96ca4c6b5 100644 --- a/subsystems/win32/csrss/csrsrv/CMakeLists.txt +++ b/subsystems/win32/csrss/csrsrv/CMakeLists.txt @@ -19,11 +19,6 @@ target_link_libraries(csrsrv ${PSEH_LIB}) set_module_type(csrsrv nativedll) -if(MSVC) -set_entrypoint(csrsrv DllMainCRTStartup) -endif() - - add_importlibs(csrsrv ntdll smdll) add_pch(csrsrv srv.h) diff --git a/subsystems/win32/csrss/csrsrv/api/process.c b/subsystems/win32/csrss/csrsrv/api/process.c index 58fb959611b..42174f03c69 100644 --- a/subsystems/win32/csrss/csrsrv/api/process.c +++ b/subsystems/win32/csrss/csrsrv/api/process.c @@ -1,5 +1,5 @@ /* - * reactos/subsys/csrss/api/process.c + * subsystems/win32/csrss/csrsrv/api/process.c * * "\windows\ApiPort" port process management functions * @@ -105,6 +105,7 @@ PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId) PROCESS_ALL_ACCESS, &ObjectAttributes, &ClientId); + DPRINT1("CSR PRocess: %p Handle: %p\n", pProcessData, pProcessData->Process); if (!NT_SUCCESS(Status)) { ProcessData[hash] = pProcessData->next; diff --git a/subsystems/win32/csrss/csrsrv/api/user.c b/subsystems/win32/csrss/csrsrv/api/user.c index de4e49f66e1..952dc24b710 100644 --- a/subsystems/win32/csrss/csrsrv/api/user.c +++ b/subsystems/win32/csrss/csrsrv/api/user.c @@ -1,6 +1,6 @@ /* $Id$ * - * reactos/subsys/csrss/api/user.c + * subsystems/win32/csrss/csrsrv/api/user.c * * User functions * diff --git a/subsystems/win32/csrss/csrsrv/api/wapi.c b/subsystems/win32/csrss/csrsrv/api/wapi.c index 88005c6fe7b..72d4e811022 100644 --- a/subsystems/win32/csrss/csrsrv/api/wapi.c +++ b/subsystems/win32/csrss/csrsrv/api/wapi.c @@ -1,6 +1,6 @@ /* $Id$ * - * reactos/subsys/csrss/api/wapi.c + * subsystems/win32/csrss/csrsrv/api/wapi.c * * CSRSS port message processing * @@ -118,6 +118,354 @@ CsrHandleHardError(IN PCSRSS_PROCESS_DATA ProcessData, (VOID)CallHardError(ProcessData, Message); } +PVOID CsrSrvSharedSectionHeap; +PVOID CsrSrvSharedSectionBase; +PVOID *CsrSrvSharedStaticServerData; +ULONG CsrSrvSharedSectionSize; +HANDLE CsrSrvSharedSection; + +/*++ + * @name CsrSrvCreateSharedSection + * + * The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server + * DLLs and Clients can use to share data. + * + * @param ParameterValue + * Specially formatted string from our registry command-line which + * specifies various arguments for the shared section. + * + * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL + * othwerwise. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrSrvCreateSharedSection(IN PCHAR ParameterValue) +{ + PCHAR SizeValue = ParameterValue; + ULONG Size; + NTSTATUS Status; + LARGE_INTEGER SectionSize; + ULONG ViewSize = 0; + SYSTEM_BASIC_INFORMATION CsrNtSysInfo; + PPEB Peb = NtCurrentPeb(); + + /* ReactOS Hackssss */ + Status = NtQuerySystemInformation(SystemBasicInformation, + &CsrNtSysInfo, + sizeof(SYSTEM_BASIC_INFORMATION), + NULL); + ASSERT(NT_SUCCESS(Status)); + + /* Find the first comma, and null terminate */ + while (*SizeValue) + { + if (*SizeValue == ',') + { + *SizeValue++ = '\0'; + break; + } + else + { + SizeValue++; + } + } + + /* Make sure it's valid */ + if (!*SizeValue) return STATUS_INVALID_PARAMETER; + + /* Convert it to an integer */ + Status = RtlCharToInteger(SizeValue, 0, &Size); + if (!NT_SUCCESS(Status)) return Status; + + /* Multiply by 1024 entries and round to page size */ + #define ROUND_UP(n,size) (((ULONG)(n) + (size - 1)) & ~(size - 1)) // hax + CsrSrvSharedSectionSize = ROUND_UP(Size * 1024, CsrNtSysInfo.PageSize); + DPRINT1("Size: %lx\n", CsrSrvSharedSectionSize); + + /* Create the Secion */ + SectionSize.LowPart = CsrSrvSharedSectionSize; + SectionSize.HighPart = 0; + Status = NtCreateSection(&CsrSrvSharedSection, + SECTION_ALL_ACCESS, + NULL, + &SectionSize, + PAGE_EXECUTE_READWRITE, + SEC_BASED | SEC_RESERVE, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Map the section */ + Status = NtMapViewOfSection(CsrSrvSharedSection, + NtCurrentProcess(), + &CsrSrvSharedSectionBase, + 0, + 0, + NULL, + &ViewSize, + ViewUnmap, + MEM_TOP_DOWN, + PAGE_EXECUTE_READWRITE); + if(!NT_SUCCESS(Status)) + { + /* Fail */ + NtClose(CsrSrvSharedSection); + return(Status); + } + + /* FIXME: Write the value to registry */ + + /* The Heap is the same place as the Base */ + CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase; + + /* Create the heap */ + if (!(RtlCreateHeap(HEAP_ZERO_MEMORY, + CsrSrvSharedSectionHeap, + CsrSrvSharedSectionSize, + PAGE_SIZE, + 0, + 0))) + { + /* Failure, unmap section and return */ + NtUnmapViewOfSection(NtCurrentProcess(), + CsrSrvSharedSectionBase); + NtClose(CsrSrvSharedSection); + return STATUS_NO_MEMORY; + } + + /* Now allocate space from the heap for the Shared Data */ + CsrSrvSharedStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap, + 0, + 4 * // HAX CSR_SERVER_DLL_MAX * + sizeof(PVOID)); + + /* Write the values to the PEB */ + Peb->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase; + Peb->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap; + Peb->ReadOnlyStaticServerData = CsrSrvSharedStaticServerData; + + /* Return */ + return STATUS_SUCCESS; +} + +/*++ + * @name CsrSrvAttachSharedSection + * + * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new + * CSR Process' address space, and returns the pointers to the section + * through the Connection Info structure. + * + * @param CsrProcess + * Pointer to the CSR Process that is attempting a connection. + * + * @param ConnectInfo + * Pointer to the CSR Connection Info structure for the incoming + * connection. + * + * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL + * othwerwise. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrSrvAttachSharedSection(IN PCSRSS_PROCESS_DATA CsrProcess OPTIONAL, + OUT PCSR_CONNECTION_INFO ConnectInfo) +{ + NTSTATUS Status; + ULONG ViewSize = 0; + + /* Check if we have a process */ + if (CsrProcess) + { + /* Map the sectio into this process */ + DPRINT1("CSR Process Handle: %p. CSR Process: %p\n", CsrProcess->Process, CsrProcess); + Status = NtMapViewOfSection(CsrSrvSharedSection, + CsrProcess->Process, + &CsrSrvSharedSectionBase, + 0, + 0, + NULL, + &ViewSize, + ViewUnmap, + SEC_NO_CHANGE, + PAGE_EXECUTE_READ); + if (Status == STATUS_CONFLICTING_ADDRESSES) + { + /* I Think our csrss tries to connect to itself... */ + DPRINT1("Multiple mapping hack\n"); + Status = STATUS_SUCCESS; + } + if (!NT_SUCCESS(Status)) return Status; + } + + /* Write the values in the Connection Info structure */ + ConnectInfo->SharedSectionBase = CsrSrvSharedSectionBase; + ConnectInfo->SharedSectionHeap = CsrSrvSharedSectionHeap; + ConnectInfo->SharedSectionData = CsrSrvSharedStaticServerData; + + /* Return success */ + return STATUS_SUCCESS; +} + +PBASE_STATIC_SERVER_DATA BaseStaticServerData; + +VOID +WINAPI +BasepFakeStaticServerData(VOID) +{ + NTSTATUS Status; + WCHAR Buffer[MAX_PATH]; + PWCHAR HeapBuffer; + UNICODE_STRING SystemRootString; + UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%"); + UNICODE_STRING BaseSrvCSDString; + UNICODE_STRING BaseSrvWindowsDirectory; + UNICODE_STRING BaseSrvWindowsSystemDirectory; + UNICODE_STRING BnoString; + RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] = + { + { + NULL, + RTL_QUERY_REGISTRY_DIRECT, + L"CSDVersion", + &BaseSrvCSDString + }, + {0} + }; + + /* Get the Windows directory */ + RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer)); + Status = RtlExpandEnvironmentStrings_U(NULL, + &UnexpandedSystemRootString, + &SystemRootString, + NULL); + DPRINT1("Status: %lx. Root: %wZ\n", Status, &SystemRootString); + ASSERT(NT_SUCCESS(Status)); + + /* Create the base directory */ + Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL; + Status = RtlCreateUnicodeString(&BaseSrvWindowsDirectory, + SystemRootString.Buffer); + ASSERT(NT_SUCCESS(Status)); + + /* Create the system directory */ + wcscat(SystemRootString.Buffer, L"\\system32"); + Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory, + SystemRootString.Buffer); + ASSERT(NT_SUCCESS(Status)); + + /* FIXME: Check Session ID */ + wcscpy(Buffer, L"\\BaseNamedObjects"); + RtlInitUnicodeString(&BnoString, Buffer); + + /* Allocate the server data */ + BaseStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap, + HEAP_ZERO_MEMORY, + sizeof(BASE_STATIC_SERVER_DATA)); + ASSERT(BaseStaticServerData != NULL); + + /* Process timezone information */ + BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID; + BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0; + Status = NtQuerySystemInformation(SystemTimeOfDayInformation, + &BaseStaticServerData->TimeOfDay, + sizeof(BaseStaticServerData->TimeOfDay), + NULL); + ASSERT(NT_SUCCESS(Status)); + + /* Make a shared heap copy of the Windows directory */ + BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory; + HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap, + 0, + BaseSrvWindowsDirectory.MaximumLength); + ASSERT(HeapBuffer); + RtlCopyMemory(HeapBuffer, + BaseStaticServerData->WindowsDirectory.Buffer, + BaseSrvWindowsDirectory.MaximumLength); + BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer; + + /* Make a shared heap copy of the System directory */ + BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory; + HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap, + 0, + BaseSrvWindowsSystemDirectory.MaximumLength); + ASSERT(HeapBuffer); + RtlCopyMemory(HeapBuffer, + BaseStaticServerData->WindowsSystemDirectory.Buffer, + BaseSrvWindowsSystemDirectory.MaximumLength); + BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer; + + /* This string is not used */ + RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory, + NULL, + 0); + + /* Make a shared heap copy of the BNO directory */ + BaseStaticServerData->NamedObjectDirectory = BnoString; + BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length + + sizeof(UNICODE_NULL); + HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap, + 0, + BaseStaticServerData->NamedObjectDirectory.MaximumLength); + ASSERT(HeapBuffer); + RtlCopyMemory(HeapBuffer, + BaseStaticServerData->NamedObjectDirectory.Buffer, + BaseStaticServerData->NamedObjectDirectory.MaximumLength); + BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer; + + /* + * Confirmed that in Windows, CSDNumber and RCNumber are actually Length + * and MaximumLength of the CSD String, since the same UNICODE_STRING is + * being queried twice, the first time as a ULONG! + * + * Somehow, in Windows this doesn't cause a buffer overflow, but it might + * in ReactOS, so this code is disabled until someone figures out WTF. + */ + BaseStaticServerData->CSDNumber = 0; + BaseStaticServerData->RCNumber = 0; + + /* Initialize the CSD string and query its value from the registry */ + RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer)); + Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, + L"", + BaseServerRegistryConfigurationTable, + NULL, + NULL); + if (NT_SUCCESS(Status)) + { + /* Copy into the shared buffer */ + wcsncpy(BaseStaticServerData->CSDVersion, + BaseSrvCSDString.Buffer, + BaseSrvCSDString.Length / sizeof(WCHAR)); + } + else + { + /* NULL-terminate to indicate nothing is there */ + BaseStaticServerData->CSDVersion[0] = UNICODE_NULL; + } + + /* Cache the system information */ + Status = NtQuerySystemInformation(SystemBasicInformation, + &BaseStaticServerData->SysInfo, + sizeof(BaseStaticServerData->SysInfo), + NULL); + ASSERT(NT_SUCCESS(Status)); + + /* FIXME: Should query the registry for these */ + BaseStaticServerData->DefaultSeparateVDM = FALSE; + BaseStaticServerData->IsWowTaskReady = FALSE; + BaseStaticServerData->LUIDDeviceMapsEnabled = FALSE; + + /* FIXME: Symlinks */ + + /* Finally, set the pointer */ + CsrSrvSharedStaticServerData[CSR_CONSOLE] = BaseStaticServerData; +} + NTSTATUS WINAPI CsrpHandleConnectionRequest (PPORT_MESSAGE Request, IN HANDLE hApiListenPort) @@ -127,23 +475,19 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request, PCSRSS_PROCESS_DATA ProcessData = NULL; REMOTE_PORT_VIEW LpcRead; CLIENT_ID ClientId; + BOOLEAN AllowConnection = FALSE; + PCSR_CONNECTION_INFO ConnectInfo; LpcRead.Length = sizeof(LpcRead); ServerPort = NULL; DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request); - Status = NtAcceptConnectPort(&ServerPort, - NULL, - Request, - TRUE, - 0, - & LpcRead); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CSR: NtAcceptConnectPort() failed\n"); - return Status; - } - + ConnectInfo = (PCSR_CONNECTION_INFO)(Request + 1); + + /* Save the process ID */ + RtlZeroMemory(ConnectInfo, sizeof(CSR_CONNECTION_INFO)); + ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess; + ProcessData = CsrGetProcessData(Request->ClientId.UniqueProcess); if (ProcessData == NULL) { @@ -152,16 +496,59 @@ CsrpHandleConnectionRequest (PPORT_MESSAGE Request, { DPRINT1("Unable to allocate or find data for process 0x%x\n", Request->ClientId.UniqueProcess); - Status = STATUS_UNSUCCESSFUL; - return Status; } } + + if (ProcessData->Process == NULL) + { + OBJECT_ATTRIBUTES ObjectAttributes; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + DPRINT1("WARNING: CSR PROCESS WITH NO CSR PROCESS HANDLE???\n"); + ClientId.UniqueThread = 0; + Status = NtOpenProcess(&ProcessData->Process, + PROCESS_ALL_ACCESS, + &ObjectAttributes, + &Request->ClientId); + DPRINT1("Status: %lx. Handle: %lx\n", Status, ProcessData->Process); + } + + if (ProcessData) + { + /* Attach the Shared Section */ + Status = CsrSrvAttachSharedSection(ProcessData, ConnectInfo); + if (NT_SUCCESS(Status)) + { + DPRINT1("Connection ok\n"); + AllowConnection = TRUE; + } + else + { + DPRINT1("Shared section map failed: %lx\n", Status); + } + } + + Status = NtAcceptConnectPort(&ServerPort, + NULL, + Request, + AllowConnection, + 0, + & LpcRead); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSR: NtAcceptConnectPort() failed\n"); + return Status; + } ProcessData->CsrSectionViewBase = LpcRead.ViewBase; ProcessData->CsrSectionViewSize = LpcRead.ViewSize; ProcessData->ServerCommunicationPort = ServerPort; - Status = NtCompleteConnectPort(ServerPort); + if (AllowConnection) Status = NtCompleteConnectPort(ServerPort); if (!NT_SUCCESS(Status)) { DPRINT1("CSR: NtCompleteConnectPort() failed\n"); diff --git a/subsystems/win32/csrss/csrsrv/init.c b/subsystems/win32/csrss/csrsrv/init.c index fa8d6273765..6ab51c2c546 100644 --- a/subsystems/win32/csrss/csrsrv/init.c +++ b/subsystems/win32/csrss/csrsrv/init.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS CSR Sub System - * FILE: subsys/csr/csrsrv/init.c + * FILE: subsystems/win32/csrss/csrsrv/init.c * PURPOSE: CSR Server DLL Initialization * PROGRAMMERS: ReactOS Portable Systems Group */ @@ -482,12 +482,23 @@ CsrpCreateBNODirectory (int argc, char ** argv, char ** envp) return Status; } + +VOID +WINAPI +BasepFakeStaticServerData(VOID); + +NTSTATUS +NTAPI +CsrSrvCreateSharedSection(IN PCHAR ParameterValue); + /********************************************************************** * CsrpCreateHeap/3 */ static NTSTATUS CsrpCreateHeap (int argc, char ** argv, char ** envp) { + CHAR Value[] = "1024,3072,512"; + NTSTATUS Status; DPRINT("CSR: %s called\n", __FUNCTION__); CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE, @@ -500,6 +511,13 @@ CsrpCreateHeap (int argc, char ** argv, char ** envp) { return STATUS_UNSUCCESSFUL; } + + + Status = CsrSrvCreateSharedSection(Value); + DPRINT1("Status: %lx\n", Status); + ASSERT(Status == STATUS_SUCCESS); + + BasepFakeStaticServerData(); return STATUS_SUCCESS; } @@ -778,9 +796,9 @@ CsrServerInitialization(ULONG ArgumentCount, BOOL NTAPI -DllMainCRTStartup(HANDLE hDll, - DWORD dwReason, - LPVOID lpReserved) +DllMain(HANDLE hDll, + DWORD dwReason, + LPVOID lpReserved) { /* We don't do much */ UNREFERENCED_PARAMETER(hDll); diff --git a/subsystems/win32/csrss/csrsrv/procsup.c b/subsystems/win32/csrss/csrsrv/procsup.c index d139d9701d6..c62bf6a3f8d 100644 --- a/subsystems/win32/csrss/csrsrv/procsup.c +++ b/subsystems/win32/csrss/csrsrv/procsup.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS CSR Sub System - * FILE: subsys/csr/csrsrv/procsup.c + * FILE: subsystems/win32/csrss/csrsrv/procsup.c * PURPOSE: CSR Process Management * PROGRAMMERS: ReactOS Portable Systems Group * Alex Ionescu @@ -26,7 +26,6 @@ extern RTL_CRITICAL_SECTION ProcessDataLock; extern PCSRSS_PROCESS_DATA ProcessData[256]; PCSRSS_PROCESS_DATA CsrRootProcess; -LIST_ENTRY CsrThreadHashTable[256]; SECURITY_QUALITY_OF_SERVICE CsrSecurityQos = { sizeof(SECURITY_QUALITY_OF_SERVICE), diff --git a/subsystems/win32/csrss/csrsrv/thredsup.c b/subsystems/win32/csrss/csrsrv/thredsup.c index e893888773b..27e5b093c0f 100644 --- a/subsystems/win32/csrss/csrsrv/thredsup.c +++ b/subsystems/win32/csrss/csrsrv/thredsup.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS CSR Sub System - * FILE: subsys/csr/csrsrv/procsup.c + * FILE: subsystems/win32/csrss/csrsrv/thredsup.c * PURPOSE: CSR Process Management * PROGRAMMERS: ReactOS Portable Systems Group * Alex Ionescu diff --git a/subsystems/win32/csrss/win32csr/CMakeLists.txt b/subsystems/win32/csrss/win32csr/CMakeLists.txt index 8b694222473..7f85f16db4a 100644 --- a/subsystems/win32/csrss/win32csr/CMakeLists.txt +++ b/subsystems/win32/csrss/win32csr/CMakeLists.txt @@ -35,7 +35,7 @@ target_link_libraries(win32csr set_module_type(win32csr win32dll) -add_importlibs(win32csr user32 gdi32 advapi32 psapi msvcrt kernel32 ntdll) +add_importlibs(win32csr user32 gdi32 advapi32 psapi kernel32 ntdll msvcrt) add_pch(win32csr w32csr.h) diff --git a/subsystems/win32/csrss/win32csr/harderror.c b/subsystems/win32/csrss/win32csr/harderror.c index ee195f7aab2..11666d644fb 100644 --- a/subsystems/win32/csrss/win32csr/harderror.c +++ b/subsystems/win32/csrss/win32csr/harderror.c @@ -106,6 +106,25 @@ CsrpGetClientFileName( return STATUS_SUCCESS; } +static +VOID +CsrpFreeStringParameters( + IN OUT PULONG_PTR Parameters, + IN PHARDERROR_MSG HardErrorMessage) +{ + ULONG nParam; + + /* Loop all parameters */ + for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) + { + /* Check if the current parameter is a string */ + if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam) && Parameters[nParam]) + { + /* Free the string buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); + } + } +} static NTSTATUS @@ -115,62 +134,82 @@ CsrpCaptureStringParameters( IN PHARDERROR_MSG HardErrorMessage, HANDLE hProcess) { - ULONG nParam, UnicodeStringParameterMask, Size = 0; - NTSTATUS Status; - UNICODE_STRING TempStringU; - CHAR *ParamString; - - UnicodeStringParameterMask = HardErrorMessage->UnicodeStringParameterMask; + ULONG nParam, Size = 0; + NTSTATUS Status = STATUS_SUCCESS; + UNICODE_STRING TempStringU, ParamStringU; + ANSI_STRING TempStringA; /* Read all strings from client space */ - for (nParam = 0; - nParam < HardErrorMessage->NumberOfParameters; - nParam++, UnicodeStringParameterMask >>= 1) + for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) { Parameters[nParam] = 0; /* Check if the current parameter is a unicode string */ - if (UnicodeStringParameterMask & 0x01) + if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) { /* Read the UNICODE_STRING from the process memory */ Status = NtReadVirtualMemory(hProcess, (PVOID)HardErrorMessage->Parameters[nParam], - &TempStringU, - sizeof(TempStringU), + &ParamStringU, + sizeof(ParamStringU), NULL); - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + break; /* Allocate a buffer for the string */ - ParamString = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - TempStringU.Length + sizeof(WCHAR)); + TempStringU.MaximumLength = ParamStringU.Length; + TempStringU.Length = ParamStringU.Length; + TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TempStringU.MaximumLength); - if (!ParamString) + if (!TempStringU.Buffer) { - DPRINT1("Cannot allocate memory %d\n", TempStringU.Length); - return STATUS_NO_MEMORY; + DPRINT1("Cannot allocate memory %u\n", TempStringU.MaximumLength); + Status = STATUS_NO_MEMORY; } /* Read the string buffer from the process memory */ Status = NtReadVirtualMemory(hProcess, + ParamStringU.Buffer, TempStringU.Buffer, - ParamString, - TempStringU.Length, + ParamStringU.Length, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status); - RtlFreeHeap(RtlGetProcessHeap(), 0, ParamString); - return Status; + RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); + break; } - /* Zero terminate the string */ - ParamString[TempStringU.Length] = 0; - ParamString[TempStringU.Length + 1] = 0; - DPRINT("ParamString=\'%S\'\n", ParamString); + DPRINT("ParamString=\'%wZ\'\n", &TempStringU); + + /* Allocate a buffer for converted to ANSI string */ + TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU); + TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TempStringA.MaximumLength); + + if (!TempStringA.Buffer) + { + DPRINT1("Cannot allocate memory %u\n", TempStringA.MaximumLength); + RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); + Status = STATUS_NO_MEMORY; + break; + } + + /* Convert string to ANSI and free temporary buffer */ + Status = RtlUnicodeStringToAnsiString(&TempStringA, &TempStringU, FALSE); + RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer); + break; + } - Parameters[nParam] = (ULONG_PTR)ParamString; + /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */ + Parameters[nParam] = (ULONG_PTR)TempStringA.Buffer; Size += TempStringU.Length; } else @@ -180,34 +219,15 @@ CsrpCaptureStringParameters( } } - *SizeOfAllUnicodeStrings = Size; - return STATUS_SUCCESS; -} - -static -VOID -CsrpFreeStringParameters( - IN OUT PULONG_PTR Parameters, - IN PHARDERROR_MSG HardErrorMessage) -{ - ULONG nParam, UnicodeStringParameterMask; - - UnicodeStringParameterMask = HardErrorMessage->UnicodeStringParameterMask; - - /* Loop all parameters */ - for (nParam = 0; - nParam < HardErrorMessage->NumberOfParameters; - nParam++, UnicodeStringParameterMask >>= 1) + if (!NT_SUCCESS(Status)) { - /* Check if the current parameter is a string */ - if (UnicodeStringParameterMask & 0x01) - { - /* Free the string buffer */ - RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); - } + CsrpFreeStringParameters(Parameters, HardErrorMessage); + return Status; } -} + *SizeOfAllUnicodeStrings = Size; + return Status; +} static NTSTATUS diff --git a/subsystems/win32/win32k/include/gdidebug.h b/subsystems/win32/win32k/include/gdidebug.h index 0f5221cc89f..5b53ec44218 100644 --- a/subsystems/win32/win32k/include/gdidebug.h +++ b/subsystems/win32/win32k/include/gdidebug.h @@ -30,7 +30,7 @@ typedef struct _LOGENTRY #if DBG_ENABLE_EVENT_LOGGING VOID NTAPI DbgDumpEventList(PSLIST_HEADER pslh); -VOID NTAPI DbgLogEvent(PSLIST_HEADER pslh, EVENT_TYPE nEventType, LPARAM lParam); +VOID NTAPI DbgLogEvent(PSLIST_HEADER pslh, LOG_EVENT_TYPE nEventType, LPARAM lParam); VOID NTAPI DbgCleanupEventList(PSLIST_HEADER pslh); #define DBG_LOGEVENT(pslh, type, val) DbgLogEvent(pslh, type, (ULONG_PTR)val) #define DBG_INITLOG(pslh) InitializeSListHead(pslh) @@ -43,28 +43,12 @@ VOID NTAPI DbgCleanupEventList(PSLIST_HEADER pslh); #define DBG_CLEANUP_EVENT_LIST(pslh) #endif -extern ULONG gulLogUnique; - -extern ULONG gulDebugChannels; - -enum _DEBUGCHANNELS -{ - DbgCustom = 1, - DbgObjects = 2, - DbgBitBlt = 4, - DbgXlate = 8, - DbgModeSwitch = 16, -}; VOID NTAPI DbgDumpGdiHandleTable(VOID); ULONG NTAPI DbgCaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture); BOOL NTAPI DbgGdiHTIntegrityCheck(VOID); VOID NTAPI DbgDumpLockedGdiHandles(VOID); -#define DBGENABLE(ch) gulDebugChannels |= (ch); -#define DBGDISABLE(ch) gulDebugChannels &= ~(ch); -#define DPRINTCH(ch) if (gulDebugChannels & (ch)) DbgPrint - #define KeRosDumpStackFrames(Frames, Count) KdSystemDebugControl('DsoR', (PVOID)Frames, Count, NULL, 0, NULL, KernelMode) NTSYSAPI ULONG APIENTRY RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags); diff --git a/subsystems/win32/win32k/include/napi.h b/subsystems/win32/win32k/include/napi.h index 9ae543bc76a..58319329f60 100644 --- a/subsystems/win32/win32k/include/napi.h +++ b/subsystems/win32/win32k/include/napi.h @@ -16,7 +16,7 @@ UCHAR Win32kSSPT[] = { #include "w32ksvc.h" }; -#define MIN_SYSCALL_NUMBER 0 +#define MIN_SYSCALL_NUMBER 0x1000 #define NUMBER_OF_SYSCALLS (sizeof(Win32kSSPT) / sizeof(Win32kSSPT[0])) -#define MAX_SYSCALL_NUMBER (NUMBER_OF_SYSCALLS - 1) +#define MAX_SYSCALL_NUMBER 0x1000 + (NUMBER_OF_SYSCALLS - 1) ULONG Win32kNumberOfSysCalls = NUMBER_OF_SYSCALLS; diff --git a/subsystems/win32/win32k/include/win32.h b/subsystems/win32/win32k/include/win32.h index 0204ff96bf1..51c0a094c2f 100644 --- a/subsystems/win32/win32k/include/win32.h +++ b/subsystems/win32/win32k/include/win32.h @@ -192,4 +192,8 @@ typedef struct _PROCESSINFO struct _GDI_POOL *pPoolDcAttr; struct _GDI_POOL *pPoolBrushAttr; struct _GDI_POOL *pPoolRgnAttr; + +#ifdef DBG + BYTE DbgChannelLevel[DbgChCount]; +#endif } PROCESSINFO; diff --git a/subsystems/win32/win32k/include/win32kdebug.h b/subsystems/win32/win32k/include/win32kdebug.h new file mode 100644 index 00000000000..2bd70465a38 --- /dev/null +++ b/subsystems/win32/win32k/include/win32kdebug.h @@ -0,0 +1,174 @@ +#pragma once + +/* + When a process is created, DbgInitDebugChannels will locate DEBUGCHANNEL + environment variable and extract information about debug channels. + This information includes which of the win32k debug channels will be + enabled for the current process and which level of a channel will be active. + This information will be stored in ppi->DbgChannelLevel. + In this way user mode can control how win32k debugging will work when + the following macros are used: ERR, FIXME, WARN, TRACE + + By default only the ERR channel will be active. Remember that other + debug channels can be activated for applications that are executed with a DEBUGCHANNEL + + Valid syntax for DEBUGCHANNEL is the following: + +UserProcess,info+UserWnd,err+UserWndpos,-listview + warn+UserMsgQ,-UserMsgGet,+shell + + Note the following: + The debug level is not required + The operation to enable/disable (+/-) and the name of the channel is required + Channels are devided by commas + No spaces are allowed + The syntax is case sensitive. Levels must be lowercase and + the names of the channels must be exactly like they are defined in DBG_DEFAULT_CHANNEL + This syntax can be mixed with wine debug channels without problems + +*/ + +#ifdef DBG + + typedef struct + { + PWCHAR Name; + ULONG Id; + } DBG_CHANNEL; + + /* note: the following values don't need to be sorted */ + enum _DEBUGCHANNELS + { + DbgChEngBlt, + DbgChEngBrush, + DbgChEngClip, + DbgChEngCursor, + DbgChEngDev, + DbgChEngErr, + DbgChEngEvent, + DbgChEngGrad, + DbgChEngLDev, + DbgChEngLine, + DbgChEngMapping, + DbgChEngPDev, + DbgChEngSurface, + DbgChEngWnd, + DbgChEngXlate, + DbgChGdiBitmap, + DbgChGdiBlt, + DbgChGdiBrush, + DbgChGdiClipRgn, + DbgChGdiCoord, + DbgChGdiDC, + DbgChGdiDCAttr, + DbgChGdiDCState, + DbgChGdiDev, + DbgChGdiDib, + DbgChGdiFont, + DbgChGdiLine, + DbgChGdiObj, + DbgChGdiPalette, + DbgChGdiPath, + DbgChGdiPen, + DbgChGdiPool, + DbgChGdiRgn, + DbgChGdiText, + DbgChGdiXFormObj, + DbgChUserAccel, + DbgChUserCalproc, + DbgChUserCaret, + DbgChUserClass, + DbgChUserClipbrd, + DbgChUserCsr, + DbgChUserDce, + DbgChUserDesktop, + DbgChUserEvent, + DbgChUserFocus, + DbgChUserHook, + DbgChUserHotkey, + DbgChUserIcon, + DbgChUserInput, + DbgChUserKbd, + DbgChUserKbdLayout, + DbgChUserMenu, + DbgChUserMetric, + DbgChUserMonitor, + DbgChUserMsgGet, + DbgChUserMsgQ, + DbgChUserMsgSend, + DbgChUserObj, + DbgChUserProcess, + DbgChUserProp, + DbgChUserScrollbar, + DbgChUserSysparam, + DbgChUserThread, + DbgChUserTimer, + DbgChUserWinsta, + DbgChUserWnd, + DbgChUserWndpos, + DbgChCount + }; + + #define DISABLED_LEVEL 0x0 + #define ERR_LEVEL 0x1 + #define FIXME_LEVEL 0x2 + #define WARN_LEVEL 0x4 + #define TRACE_LEVEL 0x8 + + #define MAX_LEVEL ERR_LEVEL | FIXME_LEVEL | WARN_LEVEL | TRACE_LEVEL + + /* the following assert is needed to make sure that the + debugging routines are not used before we get a ppi*/ + #define DBG_GET_PPI (ASSERT(PsGetCurrentProcessWin32Process()), (PPROCESSINFO)PsGetCurrentProcessWin32Process()) + #define DBG_DEFAULT_CHANNEL(x) static int DbgDefaultChannel = DbgCh##x; + + #define DBG_ENABLE_CHANNEL(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] |= level) + #define DBG_DISABLE_CHANNEL(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] &= ~level) + #define DBG_IS_CHANNEL_ENABLED(ppi,ch,level) ((ppi)->DbgChannelLevel[ch] & level) + + #define DBG_PRINT(ppi,ch,level,fmt, ...) do { \ + if(DBG_IS_CHANNEL_ENABLED(ppi,ch,level)) \ + DbgPrint("(%s:%d) " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + }while(0); + + #define ERR(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, ERR_LEVEL,"err: " fmt, __VA_ARGS__) + #define FIXME(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, FIXME_LEVEL,"fixme: " fmt, __VA_ARGS__) + #define WARN(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, WARN_LEVEL,"warn: " fmt, __VA_ARGS__) + #define TRACE(fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgDefaultChannel, TRACE_LEVEL,"trace: " fmt, __VA_ARGS__) + + #define ERR_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, ERR_LEVEL, "err: " fmt, __VA_ARGS__) + #define FIXME_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, FIXME_LEVEL, "fixme: " fmt, __VA_ARGS__) + #define WARN_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, WARN_LEVEL, "warn: " fmt, __VA_ARGS__) + #define TRACE_CH(ch,fmt, ...) DBG_PRINT(DBG_GET_PPI, DbgCh##ch, TRACE_LEVEL, "trace: " fmt, __VA_ARGS__) + + #define ERR_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, ERR_LEVEL,"err: " fmt, __VA_ARGS__) + #define FIXME_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, FIXME_LEVEL,"fixme: " fmt, __VA_ARGS__) + #define WARN_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, WARN_LEVEL,"warn: " fmt, __VA_ARGS__) + #define TRACE_PPI(ppi,ch,fmt, ...) DBG_PRINT(ppi, DbgCh##ch, TRACE_LEVEL,"trace: " fmt, __VA_ARGS__) + +#else + #define DBG_GET_PPI + #define DBG_DEFAULT_CHANNEL(x) () + + #define DBG_ENABLE_CHANNEL(ppi,ch,level) () + #define DBG_DISABLE_CHANNEL(ppi,ch,level) () + #define DBG_IS_CHANNEL_ENABLED(ppi,ch,level) () + + #define DBG_PRINT(ppi,ch,level) + + #define ERR(fmt, ...) + #define FIXME(fmt, ...) + #define WARN(fmt, ...) + #define TRACE(fmt, ...) + + #define ERR_CH(ch,fmt, ...) + #define FIXME_CH(ch,fmt, ...) + #define WARN_CH(ch,fmt, ...) + #define TRACE_CH(ch,fmt, ...) + + #define ERR_PPI(ppi,ch,fmt, ...) + #define FIXME_PPI(ppi,ch,fmt, ...) + #define WARN_PPI(ppi,ch,fmt, ...) + #define TRACE_PPI(ppi,ch,fmt, ...) +#endif + +BOOL DbgInitDebugChannels(); diff --git a/subsystems/win32/win32k/include/win32kp.h b/subsystems/win32/win32k/include/win32kp.h index 7c79d893c7b..f2843b1cf55 100644 --- a/subsystems/win32/win32k/include/win32kp.h +++ b/subsystems/win32/win32k/include/win32kp.h @@ -24,6 +24,7 @@ #define DBG_ENABLE_SERVICE_HOOKS 0 /* Internal Win32k Headers */ +#include #include #include #include diff --git a/subsystems/win32/win32k/main/dllmain.c b/subsystems/win32/win32k/main/dllmain.c index d6d2147934d..f1e16891900 100644 --- a/subsystems/win32/win32k/main/dllmain.c +++ b/subsystems/win32/win32k/main/dllmain.c @@ -67,6 +67,13 @@ Win32kProcessCallback(struct _EPROCESS *Process, PRTL_USER_PROCESS_PARAMETERS pParams = NULL; NTSTATUS Status; extern PSECTION_OBJECT GlobalUserHeapSection; + +#ifdef DBG + DbgInitDebugChannels(); +#endif + + TRACE_PPI(Win32Process, UserProcess,"Allocated ppi for PID:%d\n", Process->UniqueProcessId); + DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); /* map the global heap into the process */ diff --git a/subsystems/win32/win32k/ntuser/class.c b/subsystems/win32/win32k/ntuser/class.c index 74595eccaa3..4f298de6229 100644 --- a/subsystems/win32/win32k/ntuser/class.c +++ b/subsystems/win32/win32k/ntuser/class.c @@ -13,9 +13,6 @@ #define NDEBUG #include -#define TRACE DPRINT -#define WARN DPRINT1 -#define ERR DPRINT1 REGISTER_SYSCLASS DefaultServerClasses[] = { @@ -1636,7 +1633,7 @@ UserSetClassLongPtr(IN PCLS Class, { PULONG_PTR Data; - TRACE("SetClassLong(%d, %x)\n", Index, NewLong); + DPRINT("SetClassLong(%d, %x)\n", Index, NewLong); if (Index + sizeof(ULONG_PTR) < Index || Index + sizeof(ULONG_PTR) > Class->cbclsExtra) @@ -1944,7 +1941,7 @@ UserRegisterSystemClasses(VOID) } else { - WARN("!!! Registering system class failed!\n"); + DPRINT1("!!! Registering system class failed!\n"); Ret = FALSE; } } @@ -2269,9 +2266,9 @@ NtUserGetClassInfo( CapturedClassName = ProbeForReadUnicodeString(ClassName); if (CapturedClassName.Length == 0) - TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi); + DPRINT("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi); else - TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi); + DPRINT("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi); if (CapturedClassName.Length & 1) { @@ -2299,7 +2296,7 @@ NtUserGetClassInfo( { if (!IS_ATOM(CapturedClassName.Buffer)) { - ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n"); + DPRINT1("NtUserGetClassInfo() got ClassName instead of Atom!\n"); EngSetLastError(ERROR_INVALID_PARAMETER); Ret = FALSE; _SEH2_LEAVE; @@ -2463,7 +2460,7 @@ NtUserGetWOWClass(HINSTANCE hInstance, { if (!IS_ATOM(ClassName->Buffer)) { - ERR("NtUserGetWOWClass() got ClassName instead of Atom!\n"); + DPRINT1("NtUserGetWOWClass() got ClassName instead of Atom!\n"); Hit = TRUE; } else diff --git a/subsystems/win32/win32k/ntuser/desktop.c b/subsystems/win32/win32k/ntuser/desktop.c index b10e238fcf4..6d3c93947ce 100644 --- a/subsystems/win32/win32k/ntuser/desktop.c +++ b/subsystems/win32/win32k/ntuser/desktop.c @@ -14,9 +14,6 @@ #define NDEBUG #include -#define TRACE DPRINT -#define WARN DPRINT1 -#define ERR DPRINT1 static VOID @@ -1732,7 +1729,7 @@ IntUnmapDesktopView(IN PDESKTOP DesktopObject) PW32HEAP_USER_MAPPING HeapMapping, *PrevLink; NTSTATUS Status = STATUS_SUCCESS; - TRACE("DO %p\n"); + DPRINT("DO %p\n"); CurrentWin32Process = PsGetCurrentProcessWin32Process(); PrevLink = &CurrentWin32Process->HeapMappings.Next; diff --git a/subsystems/win32/win32k/ntuser/hook.c b/subsystems/win32/win32k/ntuser/hook.c index 466232d6b43..4885ccc2013 100644 --- a/subsystems/win32/win32k/ntuser/hook.c +++ b/subsystems/win32/win32k/ntuser/hook.c @@ -5,6 +5,7 @@ * FILE: subsystems/win32/win32k/ntuser/hook.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * James Tabor (james.tabor@rectos.org) + * Rafal Harabien (rafalh@reactos.org) * * REVISION HISTORY: * 06-06-2001 CSH Created @@ -29,15 +30,15 @@ typedef struct _HOOKPACK static LRESULT FASTCALL -IntCallLowLevelHook( PHOOK Hook, - INT Code, - WPARAM wParam, - LPARAM lParam) +co_IntCallLowLevelHook(PHOOK Hook, + INT Code, + WPARAM wParam, + LPARAM lParam) { NTSTATUS Status; PTHREADINFO pti; PHOOKPACK pHP; - INT Size; + INT Size = 0; UINT uTimeout = 300; BOOL Block = FALSE; ULONG_PTR uResult = 0; @@ -53,7 +54,6 @@ IntCallLowLevelHook( PHOOK Hook, pHP->pHk = Hook; pHP->lParam = lParam; pHP->pHookStructs = NULL; - Size = 0; // This prevents stack corruption from the caller. switch(Hook->HookId) @@ -170,13 +170,14 @@ co_HOOK_CallHookNext( PHOOK Hook, &Hook->ModuleName); } +static LRESULT FASTCALL -IntCallDebugHook( PHOOK Hook, - int Code, - WPARAM wParam, - LPARAM lParam, - BOOL Ansi) +co_IntCallDebugHook(PHOOK Hook, + int Code, + WPARAM wParam, + LPARAM lParam, + BOOL Ansi) { LRESULT lResult = 0; ULONG Size; @@ -302,13 +303,14 @@ IntCallDebugHook( PHOOK Hook, return lResult; } +static LRESULT FASTCALL -UserCallNextHookEx( PHOOK Hook, - int Code, - WPARAM wParam, - LPARAM lParam, - BOOL Ansi) +co_UserCallNextHookEx(PHOOK Hook, + int Code, + WPARAM wParam, + LPARAM lParam, + BOOL Ansi) { LRESULT lResult = 0; BOOL BadChk = FALSE; @@ -697,7 +699,7 @@ UserCallNextHookEx( PHOOK Hook, } case WH_DEBUG: - lResult = IntCallDebugHook(Hook, Code, wParam, lParam, Ansi); + lResult = co_IntCallDebugHook(Hook, Code, wParam, lParam, Ansi); break; /* @@ -740,31 +742,35 @@ IntGetHookObject(HHOOK hHook) return Hook; } -/* get the first hook in the chain */ -static -PHOOK -FASTCALL -IntGetFirstHook(PLIST_ENTRY Table) -{ - PLIST_ENTRY Elem = Table->Flink; - - if (IsListEmpty(Table)) return NULL; - - return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain); -} - static -PHOOK +HHOOK* FASTCALL -IntGetNextGlobalHook(PHOOK Hook, PDESKTOP pdo) +IntGetGlobalHookHandles(PDESKTOP pdo, int HookId) { - int HookId = Hook->HookId; - PLIST_ENTRY Elem; + PLIST_ENTRY pLastHead, pElem; + unsigned i, cHooks; + HHOOK *pList; + PHOOK pHook; + + pLastHead = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; + for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink) + ++cHooks; + + pList = ExAllocatePoolWithTag(PagedPool, (cHooks + 1) * sizeof(HHOOK), TAG_HOOK); + if(!pList) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } - Elem = Hook->Chain.Flink; - if (Elem != &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) - return CONTAINING_RECORD(Elem, HOOK, Chain); - return NULL; + for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink) + { + pHook = CONTAINING_RECORD(pElem, HOOK, Chain); + pList[i++] = pHook->head.h; + } + pList[i] = NULL; + + return pList; } /* find the next hook in the chain */ @@ -773,22 +779,23 @@ FASTCALL IntGetNextHook(PHOOK Hook) { int HookId = Hook->HookId; - PLIST_ENTRY Elem; + PLIST_ENTRY pLastHead, pElem; PTHREADINFO pti; if (Hook->Thread) { pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread); - - Elem = Hook->Chain.Flink; - if (Elem != &pti->aphkStart[HOOKID_TO_INDEX(HookId)]) - return CONTAINING_RECORD(Elem, HOOK, Chain); + pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; } else { pti = PsGetCurrentThreadWin32Thread(); - return IntGetNextGlobalHook(Hook, pti->rpdesk); + pLastHead = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; } + + pElem = Hook->Chain.Flink; + if (pElem != pLastHead) + return CONTAINING_RECORD(pElem, HOOK, Chain); return NULL; } @@ -810,7 +817,7 @@ IntFreeHook(PHOOK Hook) /* remove a hook, freeing it from the chain */ static -BOOL +VOID FASTCALL IntRemoveHook(PHOOK Hook) { @@ -837,7 +844,6 @@ IntRemoveHook(PHOOK Hook) { } _SEH2_END; - return TRUE; } } else // Global @@ -851,10 +857,8 @@ IntRemoveHook(PHOOK Hook) IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) ) { pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); - return TRUE; } } - return FALSE; } VOID @@ -875,27 +879,21 @@ HOOK_DestroyThreadHooks(PETHREAD Thread) DPRINT1("Kill Thread Hooks pti 0x%x pdo 0x%x\n",pti,pdo); return; } - ObReferenceObject(Thread); // Local Thread cleanup. if (pti->fsHooks) { for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++) { - PLIST_ENTRY pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - - if (IsListEmpty(pLLE)) continue; + PLIST_ENTRY pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - pElem = pLLE->Flink; - HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); - do + pElem = pLastHead->Flink; + while (pElem != pLastHead) { - if (!HookObj) break; - if (IntRemoveHook(HookObj)) break; - pElem = HookObj->Chain.Flink; HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); + pElem = HookObj->Chain.Flink; // get next element before hook is destroyed + IntRemoveHook(HookObj); } - while (pElem != pLLE); } pti->fsHooks = 0; } @@ -905,25 +903,19 @@ HOOK_DestroyThreadHooks(PETHREAD Thread) for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++) { PLIST_ENTRY pGLE = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; - - if (IsListEmpty(pGLE)) continue; - + pElem = pGLE->Flink; - HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); - do + while (pElem != pGLE) { - if (!HookObj) break; + HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); + pElem = HookObj->Chain.Flink; // get next element before hook is destroyed if (HookObj->head.pti == pti) { - if (IntRemoveHook(HookObj)) break; + IntRemoveHook(HookObj); } - pElem = HookObj->Chain.Flink; - HookObj = CONTAINING_RECORD(pElem, HOOK, Chain); } - while (pElem != pGLE); } } - ObDereferenceObject(Thread); return; } @@ -940,10 +932,11 @@ co_HOOK_CallHooks( INT HookId, PHOOK Hook, SaveHook; PTHREADINFO pti; PCLIENTINFO ClientInfo; - PLIST_ENTRY pLLE, pGLE; + PLIST_ENTRY pLastHead; PDESKTOP pdo; BOOL Local = FALSE, Global = FALSE; LRESULT Result = 0; + USER_REFERENCE_ENTRY Ref; ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK); @@ -992,14 +985,15 @@ co_HOOK_CallHooks( INT HookId, */ if ( Local ) { - pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - Hook = IntGetFirstHook(pLLE); - if (!Hook) + pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; + if (IsListEmpty(pLastHead)) { DPRINT1("No Local Hook Found!\n"); goto Exit; } - ObReferenceObject(Hook->Thread); + + Hook = CONTAINING_RECORD(pLastHead->Flink, HOOK, Chain); + UserRefObjectCo(Hook, &Ref); ClientInfo = pti->pClientInfo; SaveHook = pti->sphkCurrent; @@ -1043,44 +1037,46 @@ co_HOOK_CallHooks( INT HookId, } pti->sphkCurrent = SaveHook; Hook->phkNext = NULL; - ObDereferenceObject(Hook->Thread); + UserDerefObjectCo(Hook); } if ( Global ) { PTHREADINFO ptiHook; + HHOOK *pHookHandles; + unsigned i; - pGLE = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; - Hook = IntGetFirstHook(pGLE); - if (!Hook) - { - DPRINT1("No Global Hook Found!\n"); + /* Keep hooks in array because hooks can be destroyed in user world */ + pHookHandles = IntGetGlobalHookHandles(pdo, HookId); + if(!pHookHandles) goto Exit; - } + /* Performance goes down the drain. If more hooks are associated to this * hook ID, this will have to post to each of the thread message queues * or make a direct call. */ - do + for(i = 0; pHookHandles[i]; ++i) { + Hook = (PHOOK)UserGetObject(gHandleTable, pHookHandles[i], otHook); + if(!Hook) + { + DPRINT1("Invalid hook!\n"); + continue; + } + UserRefObjectCo(Hook, &Ref); + /* Hook->Thread is null, we hax around this with Hook->head.pti. */ ptiHook = Hook->head.pti; - /* "Global hook monitors messages for all threads in the same desktop - * as the calling thread." - */ - if ( ptiHook->TIF_flags & (TIF_INCLEANUP|TIF_DISABLEHOOKS) || - ptiHook->rpdesk != pdo) + if ( (pti->TIF_flags & TIF_DISABLEHOOKS) || (ptiHook->TIF_flags & TIF_INCLEANUP)) { - DPRINT("Next Hook 0x%x, 0x%x\n",ptiHook->rpdesk,pdo); - Hook = IntGetNextGlobalHook(Hook, pdo); - if (!Hook) break; + DPRINT("Next Hook 0x%x, 0x%x\n", ptiHook->rpdesk, pdo); continue; } - // Lockup the thread while this links through user world. - ObReferenceObject(ptiHook->pEThread); + if (ptiHook != pti ) - { // Block | TimeOut + { + // Block | TimeOut if ( HookId == WH_JOURNALPLAYBACK || // 1 | 0 HookId == WH_JOURNALRECORD || // 1 | 0 HookId == WH_KEYBOARD || // 1 | 200 @@ -1088,13 +1084,12 @@ co_HOOK_CallHooks( INT HookId, HookId == WH_KEYBOARD_LL || // 0 | 300 HookId == WH_MOUSE_LL ) // 0 | 300 { - DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId ); - Result = IntCallLowLevelHook(Hook, Code, wParam, lParam); + DPRINT("\nGlobal Hook posting to another Thread! %d\n", HookId); + Result = co_IntCallLowLevelHook(Hook, Code, wParam, lParam); } } else { /* Make the direct call. */ - DPRINT("\nLocal Hook calling to Thread! %d\n",HookId ); Result = co_IntCallHookProc( HookId, Code, wParam, @@ -1103,11 +1098,10 @@ co_HOOK_CallHooks( INT HookId, Hook->Ansi, &Hook->ModuleName); } - ObDereferenceObject(ptiHook->pEThread); - Hook = IntGetNextGlobalHook(Hook, pdo); + UserDerefObjectCo(Hook); } - while ( Hook ); - DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result); + ExFreePoolWithTag(pHookHandles, TAG_HOOK); + DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId, Result); } Exit: return Result; @@ -1118,7 +1112,7 @@ FASTCALL IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc) { PHOOK Hook; - PLIST_ENTRY pLLE, pLE; + PLIST_ENTRY pLastHead, pElement; PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) @@ -1129,15 +1123,13 @@ IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc) if (pti->fsHooks) { - pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - - if (IsListEmpty(pLLE)) return FALSE; + pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - pLE = pLLE->Flink; - Hook = CONTAINING_RECORD(pLE, HOOK, Chain); - do + pElement = pLastHead->Flink; + while (pElement != pLastHead) { - if (!Hook) break; + Hook = CONTAINING_RECORD(pElement, HOOK, Chain); + if (Hook->Proc == pfnFilterProc) { if (Hook->head.pti == pti) @@ -1152,10 +1144,9 @@ IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc) return FALSE; } } - pLE = Hook->Chain.Flink; - Hook = CONTAINING_RECORD(pLE, HOOK, Chain); + + pElement = Hook->Chain.Flink; } - while (pLE != pLLE); } return FALSE; } @@ -1207,7 +1198,7 @@ NtUserCallNextHookEx( int Code, if (ClientInfo && NextObj) { NextObj->phkNext = IntGetNextHook(NextObj); - lResult = UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi); + lResult = co_UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi); } RETURN( lResult); @@ -1252,14 +1243,13 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, NTSTATUS Status; HHOOK Handle; PETHREAD Thread = NULL; - PTHREADINFO ptiCurrent, pti = NULL; - BOOL Hit = FALSE; + PTHREADINFO pti, ptiHook = NULL; DECLARE_RETURN(HHOOK); DPRINT("Enter NtUserSetWindowsHookEx\n"); UserEnterExclusive(); - ptiCurrent = PsGetCurrentThreadWin32Thread(); + pti = PsGetCurrentThreadWin32Thread(); if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) { @@ -1294,11 +1284,11 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, RETURN( NULL); } - pti = Thread->Tcb.Win32Thread; + ptiHook = Thread->Tcb.Win32Thread; ObDereferenceObject(Thread); - if ( pti->rpdesk != ptiCurrent->rpdesk) // gptiCurrent->rpdesk) + if ( ptiHook->rpdesk != pti->rpdesk) // gptiCurrent->rpdesk) { DPRINT1("Local hook wrong desktop HookId: %d\n",HookId); EngSetLastError(ERROR_ACCESS_DENIED); @@ -1322,7 +1312,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, RETURN( NULL); } - if ( (pti->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) && + if ( (ptiHook->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) && (HookId == WH_GETMESSAGE || HookId == WH_CALLWNDPROC || HookId == WH_CBT || @@ -1339,7 +1329,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } else /* system-global hook */ { - pti = ptiCurrent; // gptiCurrent; + ptiHook = pti; // gptiCurrent; if ( !Mod && (HookId == WH_GETMESSAGE || HookId == WH_CALLWNDPROC || @@ -1379,68 +1369,60 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, Hook->ihmod = (INT)Mod; // Module Index from atom table, Do this for now. Hook->Thread = Thread; /* Set Thread, Null is Global. */ Hook->HookId = HookId; - Hook->rpdesk = pti->rpdesk; + Hook->rpdesk = ptiHook->rpdesk; Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */ Hook->Proc = HookProc; Hook->Ansi = Ansi; - DPRINT("Set Hook Desk 0x%x DeskInfo 0x%x Handle Desk 0x%x\n",pti->rpdesk, pti->pDeskInfo,Hook->head.rpdesk); + DPRINT("Set Hook Desk 0x%x DeskInfo 0x%x Handle Desk 0x%x\n", ptiHook->rpdesk, ptiHook->pDeskInfo,Hook->head.rpdesk); if (ThreadId) /* thread-local hook */ { - InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); - pti->sphkCurrent = NULL; - Hook->ptiHooked = pti; - pti->fsHooks |= HOOKID_TO_FLAG(HookId); + InsertHeadList(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); + ptiHook->sphkCurrent = NULL; + Hook->ptiHooked = ptiHook; + ptiHook->fsHooks |= HOOKID_TO_FLAG(HookId); - if (pti->pClientInfo) + if (ptiHook->pClientInfo) { - if ( pti->ppi == ptiCurrent->ppi) /* gptiCurrent->ppi) */ + if ( ptiHook->ppi == pti->ppi) /* gptiCurrent->ppi) */ { _SEH2_TRY { - pti->pClientInfo->fsHooks = pti->fsHooks; - pti->pClientInfo->phkCurrent = NULL; + ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks; + ptiHook->pClientInfo->phkCurrent = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Hit = TRUE; - } - _SEH2_END; - if (Hit) { DPRINT1("Problem writing to Local ClientInfo!\n"); } + _SEH2_END; } else { - KeAttachProcess(&pti->ppi->peProcess->Pcb); + KeAttachProcess(&ptiHook->ppi->peProcess->Pcb); _SEH2_TRY { - pti->pClientInfo->fsHooks = pti->fsHooks; - pti->pClientInfo->phkCurrent = NULL; + ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks; + ptiHook->pClientInfo->phkCurrent = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - Hit = TRUE; + DPRINT1("Problem writing to Remote ClientInfo!\n"); } _SEH2_END; KeDetachProcess(); - if (Hit) - { - DPRINT1("Problem writing to Remote ClientInfo!\n"); - } } } } else { - InsertHeadList(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); + InsertHeadList(&ptiHook->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); Hook->ptiHooked = NULL; //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); - pti->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); - pti->sphkCurrent = NULL; - pti->pClientInfo->phkCurrent = NULL; + ptiHook->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); + ptiHook->sphkCurrent = NULL; + ptiHook->pClientInfo->phkCurrent = NULL; } RtlInitUnicodeString(&Hook->ModuleName, NULL); diff --git a/subsystems/win32/win32k/ntuser/msgqueue.c b/subsystems/win32/win32k/ntuser/msgqueue.c index 35ed255edaa..f7aa35318db 100644 --- a/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/subsystems/win32/win32k/ntuser/msgqueue.c @@ -616,7 +616,8 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook MouseHistoryOfMoves[gcur_count].y = Msg->pt.y; MouseHistoryOfMoves[gcur_count].time = Msg->time; MouseHistoryOfMoves[gcur_count].dwExtraInfo = dwExtraInfo; - if (gcur_count++ == 64) gcur_count = 0; // 0 - 63 is 64, FIFO forwards. + if (++gcur_count == ARRAYSIZE(MouseHistoryOfMoves)) + gcur_count = 0; // 0 - 63 is 64, FIFO forwards. } // diff --git a/subsystems/win32/win32k/ntuser/painting.c b/subsystems/win32/win32k/ntuser/painting.c index fcea7dc0043..1e66ce50ce3 100644 --- a/subsystems/win32/win32k/ntuser/painting.c +++ b/subsystems/win32/win32k/ntuser/painting.c @@ -1579,110 +1579,78 @@ CLEANUP: END_CLEANUP; } - -BOOL -UserDrawSysMenuButton( - PWND pWnd, - HDC hDc, - RECTL *lpRc, - BOOL Down) -{ - HICON hIcon; - PCURICON_OBJECT pIcon; - - ASSERT(pWnd && lpRc); - - /* Get the icon to draw. We don't care about WM_GETICON here. */ - - hIcon = pWnd->pcls->hIconSm; - - if(!hIcon) - { - DPRINT("Wnd class has no small icon.\n"); - hIcon = pWnd->pcls->hIcon; - } - - if(!hIcon) - { - DPRINT("Wnd class hasn't any icon.\n"); - //FIXME: Draw "winlogo" icon. - return FALSE; - } - - if(!(pIcon = UserGetCurIconObject(hIcon))) - { - DPRINT1("UserGetCurIconObject() failed!\n"); - return FALSE; - } - - return UserDrawIconEx(hDc, lpRc->left, lpRc->top, pIcon, - UserGetSystemMetrics(SM_CXSMICON), - UserGetSystemMetrics(SM_CYSMICON), - 0, NULL, DI_NORMAL); -} - BOOL UserDrawCaptionText( HDC hDc, const PUNICODE_STRING Text, const RECTL *lpRc, - UINT uFlags) + UINT uFlags, + HFONT hFont) { - HFONT hOldFont = NULL, hFont = NULL; + HFONT hOldFont = NULL; COLORREF OldTextColor; NONCLIENTMETRICSW nclm; NTSTATUS Status; - #ifndef NDEBUG + BOOLEAN bDeleteFont = FALSE; + SIZE Size; +#ifndef NDEBUG INT i; - DPRINT("%s:", __FUNCTION__); + DPRINT(""); // print filename and line no. for(i = 0; i < Text->Length/sizeof(WCHAR); i++) DbgPrint("%C", Text->Buffer[i]); DbgPrint(", %d\n", Text->Length/sizeof(WCHAR)); - #endif +#endif nclm.cbSize = sizeof(nclm); if(!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nclm, 0)) { - DPRINT1("%s: UserSystemParametersInfo() failed!\n", __FUNCTION__); + DPRINT1("UserSystemParametersInfo() failed!\n"); return FALSE; } - IntGdiSetBkMode(hDc, TRANSPARENT); + if (!hFont) + { + if(uFlags & DC_SMALLCAP) + Status = TextIntCreateFontIndirect(&nclm.lfSmCaptionFont, &hFont); + else + Status = TextIntCreateFontIndirect(&nclm.lfCaptionFont, &hFont); - if(uFlags & DC_SMALLCAP) - Status = TextIntCreateFontIndirect(&nclm.lfSmCaptionFont, &hFont); - else Status = TextIntCreateFontIndirect(&nclm.lfCaptionFont, &hFont); + if(!NT_SUCCESS(Status)) + { + DPRINT1("TextIntCreateFontIndirect() failed! Status: 0x%x\n", Status); + return FALSE; + } - if(!NT_SUCCESS(Status)) - { - DPRINT1("%s: TextIntCreateFontIndirect() failed! Status: 0x%x\n", - __FUNCTION__, Status); - return FALSE; + bDeleteFont = TRUE; } + IntGdiSetBkMode(hDc, TRANSPARENT); + hOldFont = NtGdiSelectFont(hDc, hFont); if(!hOldFont) { - DPRINT1("%s: SelectFont() failed!\n", __FUNCTION__); - GreDeleteObject(hFont); - return FALSE; + DPRINT1("SelectFont() failed!\n"); + /* Don't fail */ } if(uFlags & DC_INBUTTON) OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(COLOR_BTNTEXT)); - else OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(uFlags & DC_ACTIVE + else + OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT)); //FIXME: If string doesn't fit to rc, truncate it and add ellipsis. - - GreExtTextOutW(hDc, lpRc->left, - lpRc->top, 0, NULL, Text->Buffer, - Text->Length/sizeof(WCHAR), NULL, 0); + GreGetTextExtentW(hDc, Text->Buffer, Text->Length/sizeof(WCHAR), &Size, 0); + GreExtTextOutW(hDc, + lpRc->left, (lpRc->top + lpRc->bottom)/2 - Size.cy/2, + 0, NULL, Text->Buffer, Text->Length/sizeof(WCHAR), NULL, 0); IntGdiSetTextColor(hDc, OldTextColor); - NtGdiSelectFont(hDc, hOldFont); - GreDeleteObject(hFont); + if (hOldFont) + NtGdiSelectFont(hDc, hOldFont); + if (bDeleteFont) + GreDeleteObject(hFont); return TRUE; } @@ -1693,51 +1661,17 @@ BOOL UserDrawCaption( RECTL *lpRc, HFONT hFont, HICON hIcon, - const PUNICODE_STRING str, + const PUNICODE_STRING Str, UINT uFlags) { BOOL Ret = FALSE; - HBITMAP hMemBmp = NULL, hOldBmp = NULL; - HBRUSH hOldBrush = NULL; - HDC hMemDc = NULL; - ULONG Height; - UINT VCenter = 0, Padding = 0; - RECTL r = *lpRc; - LONG ButtonWidth, IconWidth; + HBRUSH hBgBrush, hOldBrush = NULL; + RECTL Rect = *lpRc; BOOL HasIcon; - //ASSERT(pWnd != NULL); - RECTL_vMakeWellOrdered(lpRc); - hMemBmp = NtGdiCreateCompatibleBitmap(hDc, - lpRc->right - lpRc->left, - lpRc->bottom - lpRc->top); - - if(!hMemBmp) - { - DPRINT1("%s: NtGdiCreateCompatibleBitmap() failed!\n", __FUNCTION__); - return FALSE; - } - - hMemDc = NtGdiCreateCompatibleDC(hDc); - if(!hMemDc) - { - DPRINT1("%s: NtGdiCreateCompatibleDC() failed!\n", __FUNCTION__); - goto cleanup; - } - hOldBmp = NtGdiSelectBitmap(hMemDc, hMemBmp); - if(!hOldBmp) - { - DPRINT1("%s: NtGdiSelectBitmap() failed!\n", __FUNCTION__); - goto cleanup; - } - - Height = UserGetSystemMetrics(SM_CYCAPTION) - 1; - VCenter = (lpRc->bottom - lpRc->top) / 2; - Padding = VCenter - (Height / 2); - - if ((!hIcon) && (pWnd != NULL)) + if (!hIcon && pWnd != NULL) { HasIcon = (uFlags & DC_ICON) && (pWnd->style & WS_SYSMENU) && !(uFlags & DC_SMALLCAP) && !(pWnd->ExStyle & WS_EX_DLGMODALFRAME) @@ -1746,203 +1680,114 @@ BOOL UserDrawCaption( else HasIcon = (hIcon != 0); - IconWidth = UserGetSystemMetrics(SM_CXSIZE) + Padding; - - r.left = Padding; - r.right = r.left + (lpRc->right - lpRc->left); - r.top = Padding; - r.bottom = r.top + (Height / 2); - // Draw the caption background - if(uFlags & DC_INBUTTON) + if((uFlags & DC_GRADIENT) && !(uFlags & DC_INBUTTON)) { - hOldBrush = NtGdiSelectBrush(hMemDc, - IntGetSysColorBrush(COLOR_3DFACE)); + static GRADIENT_RECT gcap = {0, 1}; + TRIVERTEX Vertices[2]; + COLORREF Colors[2]; - if(!hOldBrush) - { - DPRINT1("%s: NtGdiSelectBrush() failed!\n", __FUNCTION__); - goto cleanup; - } + Colors[0] = IntGetSysColor((uFlags & DC_ACTIVE) ? + COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION); - if(!NtGdiPatBlt(hMemDc, 0, 0, - lpRc->right - lpRc->left, - lpRc->bottom - lpRc->top, - PATCOPY)) + Colors[1] = IntGetSysColor((uFlags & DC_ACTIVE) ? + COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION); + + Vertices[0].x = Rect.left; + Vertices[0].y = Rect.top; + Vertices[0].Red = (WORD)Colors[0]<<8; + Vertices[0].Green = (WORD)Colors[0] & 0xFF00; + Vertices[0].Blue = (WORD)(Colors[0]>>8) & 0xFF00; + Vertices[0].Alpha = 0; + + Vertices[1].x = Rect.right; + Vertices[1].y = Rect.bottom; + Vertices[1].Red = (WORD)Colors[1]<<8; + Vertices[1].Green = (WORD)Colors[1] & 0xFF00; + Vertices[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00; + Vertices[1].Alpha = 0; + + if(!GreGradientFill(hDc, Vertices, 2, &gcap, 1, GRADIENT_FILL_RECT_H)) { - DPRINT1("%s: NtGdiPatBlt() failed!\n", __FUNCTION__); + DPRINT1("GreGradientFill() failed!\n"); goto cleanup; } - - if(HasIcon) r.left+=IconWidth; } else { - r.right = (lpRc->right - lpRc->left); - if(uFlags & DC_SMALLCAP) - ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2; - else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2; + if(uFlags & DC_INBUTTON) + hBgBrush = IntGetSysColorBrush(COLOR_3DFACE); + else if(uFlags & DC_ACTIVE) + hBgBrush = IntGetSysColorBrush(COLOR_ACTIVECAPTION); + else + hBgBrush = IntGetSysColorBrush(COLOR_INACTIVECAPTION); - hOldBrush = NtGdiSelectBrush(hMemDc, - IntGetSysColorBrush(uFlags & DC_ACTIVE ? - COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION)); + hOldBrush = NtGdiSelectBrush(hDc, hBgBrush); if(!hOldBrush) { - DPRINT1("%s: NtGdiSelectBrush() failed!\n", __FUNCTION__); + DPRINT1("NtGdiSelectBrush() failed!\n"); goto cleanup; } - if(HasIcon && (uFlags & DC_GRADIENT)) - { - NtGdiPatBlt(hMemDc, 0, 0, - IconWidth+1, - lpRc->bottom - lpRc->top, - PATCOPY); - r.left+=IconWidth; - } - else + if(!NtGdiPatBlt(hDc, Rect.left, Rect.top, + Rect.right - Rect.left, + Rect.bottom - Rect.top, + PATCOPY)) { - NtGdiPatBlt(hMemDc, 0, 0, - lpRc->right - lpRc->left, - lpRc->bottom - lpRc->top, - PATCOPY); + DPRINT1("NtGdiPatBlt() failed!\n"); + goto cleanup; } - - if(uFlags & DC_GRADIENT) - { - static GRADIENT_RECT gcap = {0, 1}; - TRIVERTEX vert[2]; - COLORREF Colors[2]; - - if (pWnd != NULL) - { - if(pWnd->style & WS_SYSMENU) - { - r.right -= 3 + ButtonWidth; - if(!(uFlags & DC_SMALLCAP)) - { - if(pWnd->style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) - r.right -= 2 + 2 * ButtonWidth; - else r.right -= 2; - r.right -= 2; - } - - //Draw buttons background - if(!NtGdiSelectBrush(hMemDc, - IntGetSysColorBrush(uFlags & DC_ACTIVE ? - COLOR_GRADIENTACTIVECAPTION:COLOR_GRADIENTINACTIVECAPTION))) - { - DPRINT1("%s: NtGdiSelectBrush() failed!\n", __FUNCTION__); - goto cleanup; - } - - NtGdiPatBlt(hMemDc, - r.right, - 0, - lpRc->right - lpRc->left - r.right, - lpRc->bottom - lpRc->top, - PATCOPY); - } - } - - Colors[0] = IntGetSysColor((uFlags & DC_ACTIVE) ? - COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION); - - Colors[1] = IntGetSysColor((uFlags & DC_ACTIVE) ? - COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION); - - vert[0].x = r.left; - vert[0].y = 0; - vert[0].Red = (WORD)Colors[0]<<8; - vert[0].Green = (WORD)Colors[0] & 0xFF00; - vert[0].Blue = (WORD)(Colors[0]>>8) & 0xFF00; - vert[0].Alpha = 0; - - vert[1].x = r.right; - vert[1].y = lpRc->bottom - lpRc->top; - vert[1].Red = (WORD)Colors[1]<<8; - vert[1].Green = (WORD)Colors[1] & 0xFF00; - vert[1].Blue = (WORD)(Colors[1]>>8) & 0xFF00; - vert[1].Alpha = 0; - - if(!GreGradientFill(hMemDc, vert, 2, &gcap, - 1, GRADIENT_FILL_RECT_H)) - { - DPRINT1("%s: IntGdiGradientFill() failed!\n", __FUNCTION__); - } - - } //if(uFlags & DC_GRADIENT) } - if(HasIcon) + /* Draw icon */ + if (HasIcon) { - r.top ++; - r.left -= --IconWidth; - /* FIXME: Draw the Icon when pWnd == NULL but hIcon is valid */ - if (pWnd != NULL) - UserDrawSysMenuButton(pWnd, hMemDc, &r, FALSE); + PCURICON_OBJECT pIcon = NULL; - r.left += IconWidth; - r.top --; - } - - r.top ++; - r.left += 2; + if (!hIcon && pWnd) + { + hIcon = pWnd->pcls->hIconSm; // FIXME: Windows does not do that + if(!hIcon) + hIcon = pWnd->pcls->hIcon; + } - r.bottom = r.top + Height; + if (hIcon) + pIcon = UserGetCurIconObject(hIcon); - if((uFlags & DC_TEXT)) - { - if(!(uFlags & DC_GRADIENT)) + if (pIcon) { - r.right = (lpRc->right - lpRc->left); + LONG cx = UserGetSystemMetrics(SM_CXSMICON); + LONG cy = UserGetSystemMetrics(SM_CYSMICON); + LONG x = Rect.left - cx/2 + 1 + (Rect.bottom - Rect.top)/2; // this is really what Window does + LONG y = (Rect.top + Rect.bottom)/2 - cy/2; // center + UserDrawIconEx(hDc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL); + } + } - if(uFlags & DC_SMALLCAP) - ButtonWidth = UserGetSystemMetrics(SM_CXSMSIZE) - 2; - else ButtonWidth = UserGetSystemMetrics(SM_CXSIZE) - 2; + if (hIcon) + Rect.left += Rect.bottom - Rect.top; - if ((pWnd != NULL) && (pWnd->style & WS_SYSMENU)) - { - r.right -= 3 + ButtonWidth; - if(! (uFlags & DC_SMALLCAP)) - { - if(pWnd->style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) - r.right -= 2 + 2 * ButtonWidth; - else r.right -= 2; - r.right -= 2; - } - } - } + if((uFlags & DC_TEXT)) + { + Rect.left += 2; - /* FIXME: hFont isn't handled */ - if (str) - UserDrawCaptionText(hMemDc, str, &r, uFlags); - else if (pWnd != NULL) + if (Str) + UserDrawCaptionText(hDc, Str, &Rect, uFlags, hFont); + else if (pWnd != NULL) // FIXME: Windows does not do that { UNICODE_STRING ustr; ustr.Buffer = pWnd->strName.Buffer; ustr.Length = pWnd->strName.Length; ustr.MaximumLength = pWnd->strName.MaximumLength; - UserDrawCaptionText(hMemDc, &ustr, &r, uFlags); + UserDrawCaptionText(hDc, &ustr, &Rect, uFlags, hFont); } } - if(!NtGdiBitBlt(hDc, lpRc->left, lpRc->top, - lpRc->right - lpRc->left, lpRc->bottom - lpRc->top, - hMemDc, 0, 0, SRCCOPY, 0, 0)) - { - DPRINT1("%s: NtGdiBitBlt() failed!\n", __FUNCTION__); - goto cleanup; - } - Ret = TRUE; cleanup: - if (hOldBrush) NtGdiSelectBrush(hMemDc, hOldBrush); - if (hOldBmp) NtGdiSelectBitmap(hMemDc, hOldBmp); - if (hMemBmp) GreDeleteObject(hMemBmp); - if (hMemDc) NtGdiDeleteObjectApp(hMemDc); + if (hOldBrush) NtGdiSelectBrush(hDc, hOldBrush); return Ret; } diff --git a/subsystems/win32/win32k/objects/bitblt.c b/subsystems/win32/win32k/objects/bitblt.c index 27444939482..9be4017f917 100644 --- a/subsystems/win32/win32k/objects/bitblt.c +++ b/subsystems/win32/win32k/objects/bitblt.c @@ -903,6 +903,7 @@ NtGdiPatBlt( if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); + DPRINT1("NtGdiPatBlt on info DC!\n"); /* Yes, Windows really returns TRUE in this case */ return TRUE; } diff --git a/subsystems/win32/win32k/objects/gdidbg.c b/subsystems/win32/win32k/objects/gdidbg.c index ca48ec72f22..4d556614b56 100644 --- a/subsystems/win32/win32k/objects/gdidbg.c +++ b/subsystems/win32/win32k/objects/gdidbg.c @@ -15,9 +15,79 @@ extern ULONG gulFirstFree; extern ULONG gulFirstUnused; -ULONG gulDebugChannels = 0; ULONG gulLogUnique = 0; +/* note the following values need to be sorted */ +DBG_CHANNEL DbgChannels[DbgChCount]={ + {L"EngBlt", DbgChEngBlt}, + {L"EngBrush", DbgChEngBrush}, + {L"EngClip", DbgChEngClip}, + {L"EngCursor", DbgChEngCursor}, + {L"EngDev", DbgChEngDev}, + {L"EngErr", DbgChEngErr}, + {L"EngEvent", DbgChEngEvent}, + {L"EngGrad", DbgChEngGrad}, + {L"EngLDev", DbgChEngLDev}, + {L"EngLine", DbgChEngLine}, + {L"EngMapping", DbgChEngMapping}, + {L"EngPDev", DbgChEngPDev}, + {L"EngSurface", DbgChEngSurface}, + {L"EngWnd", DbgChEngWnd}, + {L"EngXlate", DbgChEngXlate}, + {L"GdiBitmap", DbgChGdiBitmap}, + {L"GdiBlt", DbgChGdiBlt}, + {L"GdiBrush", DbgChGdiBrush}, + {L"GdiClipRgn", DbgChGdiClipRgn}, + {L"GdiCoord", DbgChGdiCoord}, + {L"GdiDC", DbgChGdiDC}, + {L"GdiDCAttr", DbgChGdiDCAttr}, + {L"GdiDCState", DbgChGdiDCState}, + {L"GdiDev", DbgChGdiDev}, + {L"GdiDib", DbgChGdiDib}, + {L"GdiFont", DbgChGdiFont}, + {L"GdiLine", DbgChGdiLine}, + {L"GdiObj", DbgChGdiObj}, + {L"GdiPalette", DbgChGdiPalette}, + {L"GdiPath", DbgChGdiPath}, + {L"GdiPen", DbgChGdiPen}, + {L"GdiPool", DbgChGdiPool}, + {L"GdiRgn", DbgChGdiRgn}, + {L"GdiText", DbgChGdiText}, + {L"GdiXFormObj", DbgChGdiXFormObj}, + {L"UserAccel", DbgChUserAccel}, + {L"UserCalproc", DbgChUserCalproc}, + {L"UserCaret", DbgChUserCaret}, + {L"UserClass", DbgChUserClass}, + {L"UserClipbrd", DbgChUserClipbrd}, + {L"UserCsr", DbgChUserCsr}, + {L"UserDce", DbgChUserDce}, + {L"UserDesktop", DbgChUserDesktop}, + {L"UserEvent", DbgChUserEvent}, + {L"UserFocus", DbgChUserFocus}, + {L"UserHook", DbgChUserHook}, + {L"UserHotkey", DbgChUserHotkey}, + {L"UserIcon", DbgChUserIcon}, + {L"UserInput", DbgChUserInput}, + {L"UserKbd", DbgChUserKbd}, + {L"UserKbdLayout", DbgChUserKbdLayout}, + {L"UserMenu", DbgChUserMenu}, + {L"UserMetric", DbgChUserMetric}, + {L"UserMonitor", DbgChUserMonitor}, + {L"UserMsgGet", DbgChUserMsgGet}, + {L"UserMsgQ", DbgChUserMsgQ}, + {L"UserMsgSend", DbgChUserMsgSend}, + {L"UserObj", DbgChUserObj}, + {L"UserProcess", DbgChUserProcess}, + {L"UserProp", DbgChUserProp}, + {L"UserScrollbar", DbgChUserScrollbar}, + {L"UserSysparam", DbgChUserSysparam}, + {L"UserTimer", DbgChUserTimer}, + {L"UserThread", DbgChUserThread}, + {L"UserWinsta", DbgChUserWinsta}, + {L"UserWnd", DbgChUserWnd}, + {L"UserWndpos", DbgChUserWndpos} +}; + #ifdef GDI_DEBUG #if 0 static @@ -305,7 +375,7 @@ DbgDumpLockedGdiHandles() VOID NTAPI -DbgLogEvent(PSLIST_HEADER pslh, EVENT_TYPE nEventType, LPARAM lParam) +DbgLogEvent(PSLIST_HEADER pslh, LOG_EVENT_TYPE nEventType, LPARAM lParam) { PLOGENTRY pLogEntry; @@ -437,3 +507,223 @@ DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult) return ulResult; } +NTSTATUS NTAPI +QueryEnvironmentVariable(PUNICODE_STRING Name, + PUNICODE_STRING Value) +{ + NTSTATUS Status; + PWSTR wcs; + UNICODE_STRING var; + PWSTR val; + PPEB Peb; + PWSTR Environment; + + /* Ugly hack for reactos system threads */ + if(!NtCurrentTeb()) + { + return(STATUS_VARIABLE_NOT_FOUND); + } + + Peb = NtCurrentPeb(); + + if (Peb == NULL) + { + return(STATUS_VARIABLE_NOT_FOUND); + } + + Environment = Peb->ProcessParameters->Environment; + + if (Environment == NULL) + { + return(STATUS_VARIABLE_NOT_FOUND); + } + + Value->Length = 0; + + wcs = Environment; + while (*wcs) + { + var.Buffer = wcs++; + wcs = wcschr(wcs, L'='); + if (wcs == NULL) + { + wcs = var.Buffer + wcslen(var.Buffer); + } + if (*wcs) + { + var.Length = var.MaximumLength = (wcs - var.Buffer) * sizeof(WCHAR); + val = ++wcs; + wcs += wcslen(wcs); + + if (RtlEqualUnicodeString(&var, Name, TRUE)) + { + Value->Length = (wcs - val) * sizeof(WCHAR); + if (Value->Length <= Value->MaximumLength) + { + memcpy(Value->Buffer, val, + min(Value->Length + sizeof(WCHAR), Value->MaximumLength)); + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_BUFFER_TOO_SMALL; + } + + return(Status); + } + } + wcs++; + } + + return(STATUS_VARIABLE_NOT_FOUND); +} + +static int +DbgCompareChannels(const void * a, const void * b) +{ + return wcscmp((WCHAR*)a, ((DBG_CHANNEL*)b)->Name); +} + +static BOOL +DbgAddDebugChannel(PPROCESSINFO ppi, WCHAR* channel, WCHAR* level, WCHAR op) +{ + DBG_CHANNEL *ChannelEntry; + UINT iLevel, iChannel; + + DbgPrint("Found channel %S,level %S, operation %C\n", channel, level, op); + + ChannelEntry = (DBG_CHANNEL*)bsearch(channel, + DbgChannels, + DbgChCount, + sizeof(DBG_CHANNEL), + DbgCompareChannels); + if(ChannelEntry == NULL) + { + DbgPrint("Failed to find channel %S\n", channel); + return FALSE; + } + + iChannel = ChannelEntry->Id; + ASSERT(iChannel >= 0 && iChannel < DbgChCount); + + if(level == NULL || *level == L'\0' ||wcslen(level) == 0 ) + iLevel = MAX_LEVEL; + else if(wcsncmp(level, L"err", 3) == 0) + iLevel = ERR_LEVEL; + else if(wcsncmp(level, L"fixme", 5) == 0) + iLevel = FIXME_LEVEL; + else if(wcsncmp(level, L"warn", 4) == 0) + iLevel = WARN_LEVEL; + else if (wcsncmp(level, L"trace", 4) == 0) + iLevel = TRACE_LEVEL; + else + return FALSE; + + if(op==L'+') + { + DBG_ENABLE_CHANNEL(ppi, iChannel, iLevel); + } + else + { + DBG_DISABLE_CHANNEL(ppi, iChannel, iLevel); + } + + return TRUE; +} + +static BOOL +DbgParseDebugChannels(PPROCESSINFO ppi, PUNICODE_STRING Value) +{ + WCHAR *str, *separator, *c, op; + + str = Value->Buffer; + + do + { + separator = wcschr(str, L','); + if(separator != NULL) + *separator = L'\0'; + + c = wcschr(str, L'+'); + if(c == NULL) + c = wcschr(str, L'-'); + + if(c != NULL) + { + op = *c; + *c = L'\0'; + c++; + + DbgAddDebugChannel(ppi, c, str, op); + } + + str = separator + 1; + }while(separator != NULL); + + return TRUE; +} + +BOOL DbgInitDebugChannels() +{ + WCHAR valBuffer[100]; + UNICODE_STRING Value; + UNICODE_STRING Name = RTL_CONSTANT_STRING(L"DEBUGCHANNEL"); + NTSTATUS Status; + PPROCESSINFO ppi; + BOOL ret; + + /* Initialize all channels to ERROR */ + ppi = PsGetCurrentProcessWin32Process(); + RtlFillMemory( ppi->DbgChannelLevel, + sizeof(ppi->DbgChannelLevel), + ERR_LEVEL); + + /* Find DEBUGCHANNEL env var */ + Value.Buffer = valBuffer; + Value.Length = 0; + Value.MaximumLength = sizeof(valBuffer); + Status = QueryEnvironmentVariable(&Name, &Value); + + /* It does not exist */ + if(Status == STATUS_VARIABLE_NOT_FOUND) + { + /* There is nothing more to do */ + return TRUE; + } + + /* If the buffer in the stack is not enough allocate it */ + if(Status == STATUS_BUFFER_TOO_SMALL) + { + Value.Buffer = ExAllocatePool(PagedPool, Value.MaximumLength); + if(Value.Buffer == NULL) + { + return FALSE; + } + + /* Get the env var again */ + Status = QueryEnvironmentVariable(&Name, &Value); + } + + /* Check for error */ + if(!NT_SUCCESS(Status)) + { + if(Value.Buffer != valBuffer) + { + ExFreePool(Value.Buffer); + } + + return FALSE; + } + + /* Parse the variable */ + ret = DbgParseDebugChannels(ppi, &Value); + + /* Clean up*/ + if(Value.Buffer != valBuffer) + { + ExFreePool(Value.Buffer); + } + + return ret; +} + diff --git a/subsystems/win32/win32k/objects/text.c b/subsystems/win32/win32k/objects/text.c index 6c3fe7a6605..77521fc959c 100644 --- a/subsystems/win32/win32k/objects/text.c +++ b/subsystems/win32/win32k/objects/text.c @@ -15,7 +15,6 @@ /** Functions *****************************************************************/ -#if 0 /* flOpts : GetTextExtentPoint32W = 0 @@ -135,7 +134,6 @@ GreGetTextExtentExW( DC_UnlockDc(pdc); return Result; } -#endif DWORD APIENTRY diff --git a/subsystems/win32/win32k/pch.h b/subsystems/win32/win32k/pch.h index b703d6b868b..67281678916 100644 --- a/subsystems/win32/win32k/pch.h +++ b/subsystems/win32/win32k/pch.h @@ -13,6 +13,8 @@ #define _NO_COM /* DDK/NDK/SDK Headers */ +#undef NTDDI_VERSION +#define NTDDI_VERSION NTDDI_WS03SP1 #include #include #include diff --git a/tools/spec2def/spec2def.c b/tools/spec2def/spec2def.c new file mode 100644 index 00000000000..e53c20abe35 --- /dev/null +++ b/tools/spec2def/spec2def.c @@ -0,0 +1,824 @@ +#include +#include +#include +#include + +#ifdef _MSC_VER +#define strcasecmp _stricmp +#endif + +typedef struct +{ + char *pcName; + int nNameLength; + char *pcRedirection; + int nRedirectionLength; + int nCallingConvention; + int nOrdinal; + int nStackBytes; + int nArgCount; + int anArgs[30]; + unsigned int uFlags; + int nNumber; +} EXPORT; + +typedef int (*PFNOUTLINE)(FILE *, EXPORT *); +int gbKillAt = 0; +int gbUseDeco = 0; +int gbMSComp = 0; +int no_redirections = 0; +char *pszArchString = "i386"; +char *pszArchString2; +char *pszDllName = 0; + +enum +{ + FL_PRIVATE = 1, + FL_STUB = 2, + FL_NONAME = 4, +}; + +enum +{ + CC_STDCALL, + CC_CDECL, + CC_FASTCALL, + CC_EXTERN, + CC_STUB, +}; + +enum +{ + ARG_LONG, + ARG_PTR, + ARG_STR, + ARG_WSTR, + ARG_DBL, + ARG_INT64 +}; + +char* astrCallingConventions[] = +{ + "STDCALL", + "CDECL", + "FASTCALL", + "EXTERN" +}; + +static +int +IsSeparator(char chr) +{ + return ((chr <= ',' && chr != '$') || + (chr >= ':' && chr < '?') ); +} + +int +CompareToken(const char *token, const char *comparand) +{ + while (*comparand) + { + if (*token != *comparand) return 0; + token++; + comparand++; + } + if (!IsSeparator(*token)) return 0; + return 1; +} + +int +ScanToken(const char *token, char chr) +{ + while (!IsSeparator(*token)) + { + if (*token++ == chr) return 1; + } + return 0; +} + +char * +NextLine(char *pc) +{ + while (*pc != 0) + { + if (pc[0] == '\n' && pc[1] == '\r') return pc + 2; + else if (pc[0] == '\n') return pc + 1; + pc++; + } + return pc; +} + +int +TokenLength(char *pc) +{ + int length = 0; + + while (!IsSeparator(*pc++)) length++; + + return length; +} + +char * +NextToken(char *pc) +{ + /* Skip token */ + while (!IsSeparator(*pc)) pc++; + + /* Skip white spaces */ + while (*pc == ' ' || *pc == '\t') pc++; + + /* Check for end of line */ + if (*pc == '\n' || *pc == '\r' || *pc == 0) return 0; + + /* Check for comment */ + if (*pc == '#' || *pc == ';') return 0; + + return pc; +} + +void +OutputHeader_stub(FILE *file) +{ + fprintf(file, "/* This file is autogenerated, do not edit. */\n\n" + "#include \n\n"); +} + +int +OutputLine_stub(FILE *file, EXPORT *pexp) +{ + int i; + + if (pexp->nCallingConvention != CC_STUB && + (pexp->uFlags & FL_STUB) == 0) return 0; + + fprintf(file, "int "); + if (strcmp(pszArchString, "i386") == 0 && + pexp->nCallingConvention == CC_STDCALL) + { + fprintf(file, "__stdcall "); + } + + /* Check for C++ */ + if (pexp->pcName[0] == '?') + { + fprintf(file, "stub_function%d(", pexp->nNumber); + } + else + { + fprintf(file, "%.*s(", pexp->nNameLength, pexp->pcName); + } + + for (i = 0; i < pexp->nArgCount; i++) + { + if (i != 0) fprintf(file, ", "); + switch (pexp->anArgs[i]) + { + case ARG_LONG: fprintf(file, "long"); break; + case ARG_PTR: fprintf(file, "void*"); break; + case ARG_STR: fprintf(file, "char*"); break; + case ARG_WSTR: fprintf(file, "wchar_t*"); break; + case ARG_DBL: case ARG_INT64 : fprintf(file, "__int64"); break; + } + fprintf(file, " a%d", i); + } + fprintf(file, ")\n{\n\tDPRINT1(\"WARNING: calling stub %.*s(", + pexp->nNameLength, pexp->pcName); + + for (i = 0; i < pexp->nArgCount; i++) + { + if (i != 0) fprintf(file, ","); + switch (pexp->anArgs[i]) + { + case ARG_LONG: fprintf(file, "0x%%lx"); break; + case ARG_PTR: fprintf(file, "0x%%p"); break; + case ARG_STR: fprintf(file, "'%%s'"); break; + case ARG_WSTR: fprintf(file, "'%%ws'"); break; + case ARG_DBL: fprintf(file, "%%f"); break; + case ARG_INT64: fprintf(file, "%%\"PRix64\""); break; + } + } + fprintf(file, ")\\n\""); + + for (i = 0; i < pexp->nArgCount; i++) + { + fprintf(file, ", "); + switch (pexp->anArgs[i]) + { + case ARG_LONG: fprintf(file, "(long)a%d", i); break; + case ARG_PTR: fprintf(file, "(void*)a%d", i); break; + case ARG_STR: fprintf(file, "(char*)a%d", i); break; + case ARG_WSTR: fprintf(file, "(wchar_t*)a%d", i); break; + case ARG_DBL: fprintf(file, "(double)a%d", i); break; + case ARG_INT64: fprintf(file, "(__int64)a%d", i); break; + } + } + fprintf(file, ");\n"); + + if (pexp->nCallingConvention == CC_STUB) + { + fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName); + } + + fprintf(file, "\treturn 0;\n}\n\n"); + + return 1; +} + +void +OutputHeader_asmstub(FILE *file, char *libname) +{ + fprintf(file, "; File generated automatically, do not edit! \n\n" + ".586\n.model flat\n.code\n"); +} + +int +OutputLine_asmstub(FILE *fileDest, EXPORT *pexp) +{ + /* Handle autoname */ + if (pexp->nNameLength == 1 && pexp->pcName[0] == '@') + { + fprintf(fileDest, "PUBLIC ordinal%d\nordinal%d: nop\n", + pexp->nOrdinal, pexp->nOrdinal); + } + else if (pexp->nCallingConvention == CC_STDCALL) + { + fprintf(fileDest, "PUBLIC _%.*s@%d\n_%.*s@%d: nop\n", + pexp->nNameLength, pexp->pcName, pexp->nStackBytes, + pexp->nNameLength, pexp->pcName, pexp->nStackBytes); + } + else if (pexp->nCallingConvention == CC_FASTCALL) + { + fprintf(fileDest, "PUBLIC @%.*s@%d\n@%.*s@%d: nop\n", + pexp->nNameLength, pexp->pcName, pexp->nStackBytes, + pexp->nNameLength, pexp->pcName, pexp->nStackBytes); + } + else if (pexp->nCallingConvention == CC_CDECL || + pexp->nCallingConvention == CC_STUB) + { + fprintf(fileDest, "PUBLIC _%.*s\n_%.*s: nop\n", + pexp->nNameLength, pexp->pcName, + pexp->nNameLength, pexp->pcName); + } + else if (pexp->nCallingConvention == CC_EXTERN) + { + fprintf(fileDest, "PUBLIC _%.*s\n_%.*s:\n", + pexp->nNameLength, pexp->pcName, + pexp->nNameLength, pexp->pcName); + } + + return 1; +} + +void +OutputHeader_def(FILE *file, char *libname) +{ + fprintf(file, + "; File generated automatically, do not edit!\n\n" + "LIBRARY %s\n\n" + "EXPORTS\n", + libname); +} + +void +PrintName(FILE *fileDest, EXPORT *pexp, int fRedir, int fDeco) +{ + char *pcName = fRedir ? pexp->pcRedirection : pexp->pcName; + int nNameLength = fRedir ? pexp->nRedirectionLength : pexp->nNameLength; + + if (fDeco && pexp->nCallingConvention == CC_FASTCALL) + fprintf(fileDest, "@"); + fprintf(fileDest, "%.*s", nNameLength, pcName); + if ((pexp->nCallingConvention == CC_STDCALL || + pexp->nCallingConvention == CC_FASTCALL) && fDeco) + { + fprintf(fileDest, "@%d", pexp->nStackBytes); + } +} + +int +OutputLine_def(FILE *fileDest, EXPORT *pexp) +{ + fprintf(fileDest, " "); + + /* Handle autoname */ + if (pexp->nNameLength == 1 && pexp->pcName[0] == '@') + { + fprintf(fileDest, "ordinal%d", pexp->nOrdinal); + } + else + { + PrintName(fileDest, pexp, 0, gbUseDeco && !gbKillAt); + } + + if (pexp->pcRedirection && !no_redirections) + { + int fDeco = (gbUseDeco && !ScanToken(pexp->pcRedirection, '.')); + + fprintf(fileDest, "="); + PrintName(fileDest, pexp, 1, fDeco && !gbMSComp); + } + else if (((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) && + (pexp->pcName[0] == '?')) + { + /* C++ stubs are forwarded to C stubs */ + fprintf(fileDest, "="); + fprintf(fileDest, "stub_function%d", pexp->nNumber); + } + else if ((giArch == ARCH_X86) && gbKillAt && !gbMSComp && + (pexp->nCallingConvention == CC_STDCALL || + pexp->nCallingConvention == CC_FASTCALL)) + { + fprintf(fileDest, "="); + PrintName(fileDest, pexp, 0, 1); + } + + if (pexp->nOrdinal != -1) + { + fprintf(fileDest, " @%d", pexp->nOrdinal); + } + + if (pexp->nCallingConvention == CC_EXTERN) + { + fprintf(fileDest, " DATA"); + } + + if (pexp->uFlags & FL_PRIVATE) + { + fprintf(fileDest, " PRIVATE"); + } + + if (pexp->uFlags & FL_NONAME) + { + fprintf(fileDest, " NONAME"); + } + + fprintf(fileDest, "\n"); + + return 1; +} + +int +ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine) +{ + char *pc, *pcLine; + int nLine; + EXPORT exp; + int included; + + //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart); + + /* Loop all lines */ + nLine = 1; + exp.nNumber = 0; + for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++) + { + pc = pcLine; + + exp.nArgCount = 0; + exp.uFlags = 0; + exp.nNumber++; + + //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n", + // nLine, TokenLength(pcLine), pcLine); + + /* Skip white spaces */ + while (*pc == ' ' || *pc == '\t') pc++; + + /* Skip empty lines, stop at EOF */ + if (*pc == ';' || *pc <= '#') continue; + if (*pc == 0) return 0; + + //fprintf(stderr, "info: line %d, token:'%.*s'\n", + // nLine, TokenLength(pc), pc); + + /* Now we should get either an ordinal or @ */ + if (*pc == '@') exp.nOrdinal = -1; + else exp.nOrdinal = atol(pc); + + /* Go to next token (type) */ + if (!(pc = NextToken(pc))) + { + fprintf(stderr, "error: line %d, unexpected end of line\n", nLine); + return -10; + } + + //fprintf(stderr, "info: Token:'%.10s'\n", pc); + + /* Now we should get the type */ + if (CompareToken(pc, "stdcall")) + { + exp.nCallingConvention = CC_STDCALL; + } + else if (CompareToken(pc, "cdecl") || + CompareToken(pc, "varargs")) + { + exp.nCallingConvention = CC_CDECL; + } + else if (CompareToken(pc, "fastcall")) + { + exp.nCallingConvention = CC_FASTCALL; + } + else if (CompareToken(pc, "extern")) + { + exp.nCallingConvention = CC_EXTERN; + } + else if (CompareToken(pc, "stub")) + { + exp.nCallingConvention = CC_STUB; + } + else + { + fprintf(stderr, "error: line %d, expected type, got '%.*s' %d\n", + nLine, TokenLength(pc), pc, *pc); + return -11; + } + + //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention); + + /* Go to next token (options or name) */ + if (!(pc = NextToken(pc))) + { + fprintf(stderr, "fail2\n"); + return -12; + } + + /* Handle options */ + included = 1; + while (*pc == '-') + { + if (CompareToken(pc, "-arch")) + { + /* Default to not included */ + included = 0; + pc += 5; + + /* Look if we are included */ + while (*pc == '=' || *pc == ',') + { + pc++; + if (CompareToken(pc, pszArchString) || + CompareToken(pc, pszArchString2)) + { + included = 1; + } + + /* Skip to next arch or end */ + while (*pc > ',') pc++; + } + } + else if (CompareToken(pc, "-i386")) + { + if (strcasecmp(pszArchString, "i386") != 0) included = 0; + } + else if (CompareToken(pc, "-private")) + { + exp.uFlags |= FL_PRIVATE; + } + else if (CompareToken(pc, "-noname") || + CompareToken(pc, "-ordinal")) + { + exp.uFlags |= FL_NONAME; + } + else if (CompareToken(pc, "-stub")) + { + exp.uFlags |= FL_STUB; + } + else if (CompareToken(pc, "-norelay") || + CompareToken(pc, "-register") || + CompareToken(pc, "-ret64")) + { + /* silently ignore these */ + } + else + { + fprintf(stderr, "info: ignored option: '%.*s'\n", + TokenLength(pc), pc); + } + + /* Go to next token */ + pc = NextToken(pc); + } + + //fprintf(stderr, "info: Name:'%.10s'\n", pc); + + /* If arch didn't match ours, skip this entry */ + if (!included) continue; + + /* Get name */ + exp.pcName = pc; + exp.nNameLength = TokenLength(pc); + + /* Handle parameters */ + exp.nStackBytes = 0; + if (exp.nCallingConvention != CC_EXTERN && + exp.nCallingConvention != CC_STUB) + { + //fprintf(stderr, "info: options:'%.10s'\n", pc); + /* Go to next token */ + if (!(pc = NextToken(pc))) + { + fprintf(stderr, "fail4\n"); + return -13; + } + + /* Verify syntax */ + if (*pc++ != '(') + { + fprintf(stderr, "error: line %d, expected '('\n", nLine); + return -14; + } + + /* Skip whitespaces */ + while (*pc == ' ' || *pc == '\t') pc++; + + exp.nStackBytes = 0; + while (*pc >= '0') + { + if (CompareToken(pc, "long")) + { + exp.nStackBytes += 4; + exp.anArgs[exp.nArgCount] = ARG_LONG; + } + else if (CompareToken(pc, "double")) + { + exp.nStackBytes += 8; + exp.anArgs[exp.nArgCount] = ARG_DBL; + } + else if (CompareToken(pc, "ptr") || + CompareToken(pc, "str") || + CompareToken(pc, "wstr")) + { + exp.nStackBytes += 4; // sizeof(void*) on x86 + exp.anArgs[exp.nArgCount] = ARG_PTR; // FIXME: handle strings + } + else if (CompareToken(pc, "int64")) + { + exp.nStackBytes += 8; + exp.anArgs[exp.nArgCount] = ARG_INT64; + } + else + fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc); + + exp.nArgCount++; + + /* Go to next parameter */ + if (!(pc = NextToken(pc))) + { + fprintf(stderr, "fail5\n"); + return -15; + } + } + + /* Check syntax */ + if (*pc++ != ')') + { + fprintf(stderr, "error: line %d, expected ')'\n", nLine); + return -16; + } + } + + /* Handle special stub cases */ + if (exp.nCallingConvention == CC_STUB) + { + /* Check for c++ mangled name */ + if (pc[0] == '?') + { + //printf("Found c++ mangled name...\n"); + // + } + else + { + /* Check for stdcall name */ + char *p = strchr(pc, '@'); + if (p && (p - pc < exp.nNameLength)) + { + int i; + exp.nNameLength = p - pc; + if (exp.nNameLength < 1) + { + fprintf(stderr, "error, @ in line %d\n", nLine); + return -1; + } + exp.nStackBytes = atoi(p + 1); + exp.nArgCount = exp.nStackBytes / 4; + exp.nCallingConvention = CC_STDCALL; + exp.uFlags |= FL_STUB; + for (i = 0; i < exp.nArgCount; i++) + exp.anArgs[i] = ARG_LONG; + } + } + } + + /* Get optional redirection */ + if ((pc = NextToken(pc))) + { + exp.pcRedirection = pc; + exp.nRedirectionLength = TokenLength(pc); + + /* Check syntax (end of line) */ + if (NextToken(pc)) + { + fprintf(stderr, "error: line %d, additional tokens after ')'\n", nLine); + return -17; + } + } + else + { + exp.pcRedirection = 0; + exp.nRedirectionLength = 0; + } + + OutputLine(fileDest, &exp); + } + + return 0; +} + + +void usage(void) +{ + printf("syntax: spec2pdef [ ...] \n" + "Possible options:\n" + " -h --help prints this screen\n" + " -l= generates an asm lib stub\n" + " -d= generates a def file\n" + " -s= generates a stub file\n" + " --ms msvc compatibility\n" + " -n= name of the dll\n" + " --kill-at removes @xx decorations from exports\n" + " -r removes redirections from def file\n" + " -a= Set architecture to . (i386, x86_64, arm)\n"); +} + +int main(int argc, char *argv[]) +{ + size_t nFileSize; + char *pszSource, *pszDefFileName = 0, *pszStubFileName = 0, *pszLibStubName = 0; + char achDllName[40]; + FILE *file; + int result, i; + + if (argc < 2) + { + usage(); + return -1; + } + + /* Read options */ + for (i = 1; i < argc && *argv[i] == '-'; i++) + { + if ((strcasecmp(argv[i], "--help") == 0) || + (strcasecmp(argv[i], "-h") == 0)) + { + usage(); + return 0; + } + else if (argv[i][1] == 'd' && argv[i][2] == '=') + { + pszDefFileName = argv[i] + 3; + } + else if (argv[i][1] == 'l' && argv[i][2] == '=') + { + pszLibStubName = argv[i] + 3; + } + else if (argv[i][1] == 's' && argv[i][2] == '=') + { + pszStubFileName = argv[i] + 3; + } + else if (argv[i][1] == 'n' && argv[i][2] == '=') + { + pszDllName = argv[i] + 3; + } + else if ((strcasecmp(argv[i], "--kill-at") == 0)) + { + gbKillAt = 1; + } + else if ((strcasecmp(argv[i], "--ms") == 0)) + { + gbMSComp = 1; + } + else if ((strcasecmp(argv[i], "-r") == 0)) + { + no_redirections = 1; + } + else if (argv[i][1] == 'a' && argv[i][2] == '=') + { + pszArchString = argv[i] + 3; + } + else + { + fprintf(stderr, "Unrecognized option: %s\n", argv[i]); + return -1; + } + } + + if ((strcasecmp(pszArchString, "x86_64") == 0) || + (strcasecmp(pszArchString, "ia64") == 0)) + { + pszArchString2 = "win64"; + } + else + pszArchString2 = "win32"; + + if (strcasecmp(pszArchString, "i386") == 0) + { + gbUseDeco = 1; + } + + /* Set a default dll name */ + if (!pszDllName) + { + char *p1, *p2; + int len; + + p1 = strrchr(argv[i], '\\'); + if (!p1) p1 = strrchr(argv[i], '/'); + p2 = p1 = p1 ? p1 + 1 : argv[i]; + + /* walk up to '.' */ + while (*p2 != '.' && *p2 != 0) p2++; + len = p2 - p1; + if (len >= sizeof(achDllName) - 5) + { + fprintf(stderr, "name too long: %s\n", p1); + return -2; + } + + strncpy(achDllName, p1, len); + strncpy(achDllName + len, ".dll", sizeof(achDllName) - len); + pszDllName = achDllName; + } + + /* Open input file argv[1] */ + file = fopen(argv[i], "r"); + if (!file) + { + fprintf(stderr, "error: could not open file %s ", argv[i]); + return -3; + } + + /* Get file size */ + fseek(file, 0, SEEK_END); + nFileSize = ftell(file); + rewind(file); + + /* Allocate memory buffer */ + pszSource = malloc(nFileSize + 1); + if (!pszSource) return -4; + + /* Load input file into memory */ + nFileSize = fread(pszSource, 1, nFileSize, file); + fclose(file); + + /* Zero terminate the source */ + pszSource[nFileSize] = '\0'; + + if (pszDefFileName) + { + /* Open output file */ + file = fopen(pszDefFileName, "w"); + if (!file) + { + fprintf(stderr, "error: could not open output file %s ", argv[i + 1]); + return -5; + } + + OutputHeader_def(file, pszDllName); + result = ParseFile(pszSource, file, OutputLine_def); + fclose(file); + } + + if (pszStubFileName) + { + /* Open output file */ + file = fopen(pszStubFileName, "w"); + if (!file) + { + fprintf(stderr, "error: could not open output file %s ", argv[i + 1]); + return -5; + } + + OutputHeader_stub(file); + result = ParseFile(pszSource, file, OutputLine_stub); + fclose(file); + } + + if (pszLibStubName) + { + /* Open output file */ + file = fopen(pszLibStubName, "w"); + if (!file) + { + fprintf(stderr, "error: could not open output file %s ", argv[i + 1]); + return -5; + } + + OutputHeader_asmstub(file, pszDllName); + result = ParseFile(pszSource, file, OutputLine_asmstub); + fprintf(file, "\nEND\n"); + fclose(file); + } + + + return result; +}