ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
December 2018
----- 2024 -----
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
26 participants
322 discussions
Start a n
N
ew thread
[reactos] 01/04: [PSDK] PSDK-compatibility: Add the SList function declarations to winbase.h.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f6baf266e10324039969c…
commit f6baf266e10324039969cbdeb47f35c1feded9fc Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sat Dec 15 16:21:24 2018 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Dec 15 20:19:29 2018 +0100 [PSDK] PSDK-compatibility: Add the SList function declarations to winbase.h. --- sdk/include/psdk/winbase.h | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/sdk/include/psdk/winbase.h b/sdk/include/psdk/winbase.h index 8e46723667..5f2c867ac2 100644 --- a/sdk/include/psdk/winbase.h +++ b/sdk/include/psdk/winbase.h @@ -3883,11 +3883,41 @@ InitOnceExecuteOnce( _Inout_opt_ PVOID Parameter, _Outptr_opt_result_maybenull_ LPVOID *Context); + +#if defined(_SLIST_HEADER_) && !defined(_NTOS_) && !defined(_NTOSP_) + WINBASEAPI VOID WINAPI InitializeSListHead( - _Out_ PSLIST_HEADER ListHead); + _Out_ PSLIST_HEADER ListHead); + +WINBASEAPI +PSLIST_ENTRY +WINAPI +InterlockedPopEntrySList( + _Inout_ PSLIST_HEADER ListHead); + +WINBASEAPI +PSLIST_ENTRY +WINAPI +InterlockedPushEntrySList( + _Inout_ PSLIST_HEADER ListHead, + _Inout_ PSLIST_ENTRY ListEntry); + +WINBASEAPI +PSLIST_ENTRY +WINAPI +InterlockedFlushSList( + _Inout_ PSLIST_HEADER ListHead); + +WINBASEAPI +USHORT +WINAPI +QueryDepthSList( + _In_ PSLIST_HEADER ListHead); + +#endif /* _SLIST_HEADER_ */ #ifdef _MSC_VER #pragma warning(pop)
5 years, 10 months
1
0
0
0
[reactos] 02/02: [SHELL32] Update Simplified Chinese translation.
by Luo Yufan
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=adf023e38c658f37b1b81…
commit adf023e38c658f37b1b8166c5b1f6c52627e6481 Author: Luo Yufan <njlyf2011(a)hotmail.com> AuthorDate: Sat Dec 15 23:19:53 2018 +0800 Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Dec 15 20:13:47 2018 +0100 [SHELL32] Update Simplified Chinese translation. --- dll/win32/shell32/lang/zh-CN.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dll/win32/shell32/lang/zh-CN.rc b/dll/win32/shell32/lang/zh-CN.rc index 12f9b68681..f837f22018 100644 --- a/dll/win32/shell32/lang/zh-CN.rc +++ b/dll/win32/shell32/lang/zh-CN.rc @@ -501,7 +501,7 @@ CAPTION "注销 ReactOS" FONT 9, "宋体" BEGIN ICON IDI_SHELL_LOGOFF, IDC_STATIC, 8, 6, 21, 20 - LTEXT "确实要注销吗?", -1, 35, 16, 146, 8 + LTEXT "您确定要注销 ReactOS 吗?", -1, 35, 16, 146, 8 DEFPUSHBUTTON "注销(&L)", IDOK, 41, 39, 50, 14 PUSHBUTTON "取消", IDCANCEL, 95, 39, 50, 14 END
5 years, 10 months
1
0
0
0
[reactos] 01/02: [SHELL32] Update Traditional Chinese translation.
by Luo Yufan
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f369ae618d12d3dc49f02…
commit f369ae618d12d3dc49f02b0f59152512945074dc Author: Luo Yufan <njlyf2011(a)hotmail.com> AuthorDate: Sat Dec 15 23:18:02 2018 +0800 Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Dec 15 20:13:47 2018 +0100 [SHELL32] Update Traditional Chinese translation. --- dll/win32/shell32/lang/zh-TW.rc | 171 ++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 85 deletions(-) diff --git a/dll/win32/shell32/lang/zh-TW.rc b/dll/win32/shell32/lang/zh-TW.rc index 5fcd310f27..bc191ef164 100644 --- a/dll/win32/shell32/lang/zh-TW.rc +++ b/dll/win32/shell32/lang/zh-TW.rc @@ -4,6 +4,7 @@ * FILE: dll/win32/shell32/lang/zh-TW.rc * PURPOSE: Chinese (Traditional) Language Resources * TRANSLATOR: Elton Chung aka MfldElton <elton328(a)gmail.com> + * Luo Yufan <njlyf2011(a)hotmail.com> */ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL @@ -27,7 +28,7 @@ MENU_002 MENUEX BEGIN POPUP "" BEGIN - POPUP "&View", FCIDM_SHVIEW_VIEW + POPUP "檢視(&V)", FCIDM_SHVIEW_VIEW BEGIN MENUITEM "大圖示(&G)", FCIDM_SHVIEW_BIGICON MENUITEM "小圖示(&M)", FCIDM_SHVIEW_SMALLICON @@ -52,18 +53,18 @@ END /* menubar EDIT menu */ MENU_003 MENU BEGIN - MENUITEM "&Undo\tCtrl+Z", FCIDM_SHVIEW_UNDO + MENUITEM "復原(&U)\tCtrl+Z", FCIDM_SHVIEW_UNDO MENUITEM SEPARATOR - MENUITEM "Cu&t\tCtrl+X", FCIDM_SHVIEW_CUT - MENUITEM "&Copy\tCtrl+C", FCIDM_SHVIEW_COPY - MENUITEM "&Paste\tCtrl+V", FCIDM_SHVIEW_INSERT - MENUITEM "Paste &shortcut", FCIDM_SHVIEW_INSERTLINK + MENUITEM "剪下(&U)\tCtrl+X", FCIDM_SHVIEW_CUT + MENUITEM "複製(&C)\tCtrl+C", FCIDM_SHVIEW_COPY + MENUITEM "貼上(&P)\tCtrl+V", FCIDM_SHVIEW_INSERT + MENUITEM "貼上捷徑(&S)", FCIDM_SHVIEW_INSERTLINK MENUITEM SEPARATOR - MENUITEM "Copy to &folder...", FCIDM_SHVIEW_COPYTO - MENUITEM "Mo&ve to folder...", FCIDM_SHVIEW_MOVETO + MENUITEM "複製到資料夾...(&F)", FCIDM_SHVIEW_COPYTO + MENUITEM "移動到資料夾...(&V)", FCIDM_SHVIEW_MOVETO MENUITEM SEPARATOR - MENUITEM "Select &all\tCtrl+A", FCIDM_SHVIEW_SELECTALL - MENUITEM "&Invert Selection", FCIDM_SHVIEW_INVERTSELECTION + MENUITEM "全選(&A)\tCtrl+A", FCIDM_SHVIEW_SELECTALL + MENUITEM "反選(&I)", FCIDM_SHVIEW_INVERTSELECTION END /* shellview item menu */ @@ -72,14 +73,14 @@ BEGIN POPUP "" BEGIN MENUITEM SEPARATOR - MENUITEM "C&ut", IDM_CUT - MENUITEM "&Copy", IDM_COPY + MENUITEM "剪下(&U)", IDM_CUT + MENUITEM "複製(&C)", IDM_COPY MENUITEM SEPARATOR - MENUITEM "Create &Link", IDM_CREATELINK - MENUITEM "&Delete", IDM_DELETE - MENUITEM "&Rename", IDM_RENAME + MENUITEM "建立捷徑(&L)", IDM_CREATELINK + MENUITEM "刪除(&D)", IDM_DELETE + MENUITEM "重新命名(&R)", IDM_RENAME MENUITEM SEPARATOR - MENUITEM "&Properties", IDM_PROPERTIES + MENUITEM "內容(&P)", IDM_PROPERTIES END END @@ -87,21 +88,21 @@ IDM_DRAGFILE MENU BEGIN POPUP "" BEGIN - MENUITEM "&Copy here", IDM_COPYHERE - MENUITEM "&Move here", IDM_MOVEHERE - MENUITEM "Create &shortcuts here", IDM_LINKHERE + MENUITEM "複製到這裡(&C)", IDM_COPYHERE + MENUITEM "移動到這裡(&M)", IDM_MOVEHERE + MENUITEM "在這裡建立捷徑(&S)", IDM_LINKHERE MENUITEM SEPARATOR - MENUITEM "Cancel", 0 + MENUITEM "取消", 0 END END IDD_BROWSE_FOR_FOLDER DIALOGEX 15, 40, 188, 192 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Browse for Folder" +CAPTION "瀏覽資料夾" FONT 9, "新細明體" BEGIN - DEFPUSHBUTTON "OK", 1, 60, 175, 60, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Cancel", 2, 125, 175, 60, 15, WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "確定", 1, 60, 175, 60, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "取消", 2, 125, 175, 60, 15, WS_GROUP | WS_TABSTOP LTEXT "", IDC_BROWSE_FOR_FOLDER_TITLE, 4, 4, 180, 12 LTEXT "", IDC_BROWSE_FOR_FOLDER_STATUS, 4, 25, 180, 12 CONTROL "", IDC_BROWSE_FOR_FOLDER_TREEVIEW, "SysTreeView32", TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS | WS_BORDER | WS_TABSTOP, 4, 40, 180, 120 @@ -109,17 +110,17 @@ END IDD_BROWSE_FOR_FOLDER_NEW DIALOGEX 15, 40, 218, 196 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Browse for Folder" +CAPTION "瀏覽資料夾" FONT 9, "新細明體" BEGIN LTEXT "", IDC_BROWSE_FOR_FOLDER_TITLE, 10, 8, 198, 24 LTEXT "", IDC_BROWSE_FOR_FOLDER_STATUS, 10, 25, 198, 12 - LTEXT "Folder:", IDC_BROWSE_FOR_FOLDER_FOLDER, 10, 152, 40, 12 + LTEXT "資料夾:", IDC_BROWSE_FOR_FOLDER_FOLDER, 10, 152, 40, 12 CONTROL "", IDC_BROWSE_FOR_FOLDER_TREEVIEW, "SysTreeView32", TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | WS_BORDER | WS_TABSTOP, 12, 38, 194, 105 EDITTEXT IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT, 46, 150, 160, 14, WS_BORDER | WS_GROUP | WS_TABSTOP PUSHBUTTON "&Make New Folder", IDC_BROWSE_FOR_FOLDER_NEW_FOLDER, 12, 174, 77, 14, WS_GROUP | WS_TABSTOP - DEFPUSHBUTTON "OK", IDOK, 102, 174, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 156, 174, 50, 14, WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "確定", IDOK, 102, 174, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "取消", IDCANCEL, 156, 174, 50, 14, WS_GROUP | WS_TABSTOP END IDD_YESTOALL_MSGBOX DIALOGEX 200, 100, 280, 90 @@ -127,10 +128,10 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS CAPTION "訊息" FONT 9, "新細明體" BEGIN - DEFPUSHBUTTON "&Yes", IDYES, 34, 69, 53, 14, WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "是(&Y)", IDYES, 34, 69, 53, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "Yes to &all", IDC_YESTOALL, 92, 69, 65, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "&No", IDNO, 162, 69, 53, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "&Cancel", IDCANCEL, 220, 69, 53, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "否(&N)", IDNO, 162, 69, 53, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "取消(&C)", IDCANCEL, 220, 69, 53, 14, WS_GROUP | WS_TABSTOP ICON "", IDC_YESTOALL_ICON, 10, 10, 16, 16 LTEXT "", IDC_YESTOALL_MESSAGE, 40, 10, 238, 52, 0 END @@ -171,44 +172,44 @@ END IDD_RUN DIALOGEX 0, 0, 227, 95 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Run" +CAPTION "執行" FONT 9, "新細明體" BEGIN ICON "", IDC_RUNDLG_ICON, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 + LTEXT "請輸入程式、資料夾、文件或網際網路的资源名稱,ReactOS 將幫助您打開。", 12289, 36, 11, 182, 18 + LTEXT "開啟(&O):", 12305, 7, 39, 24, 10 CONTROL "", IDC_RUNDLG_EDITPATH, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 184, 100 - DEFPUSHBUTTON "OK", IDOK, 36, 70, 59, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 98, 70, 59, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 160, 70, 59, 14, WS_TABSTOP + DEFPUSHBUTTON "確定", IDOK, 36, 70, 59, 14, WS_TABSTOP + PUSHBUTTON "取消", IDCANCEL, 98, 70, 59, 14, WS_TABSTOP + PUSHBUTTON "瀏覽(&B)...", 12288, 160, 70, 59, 14, WS_TABSTOP END IDD_SHORTCUT_PROPERTIES DIALOGEX 0, 0, 235, 215 STYLE DS_SHELLFONT | WS_CHILD | WS_CAPTION -CAPTION "Shortcut" +CAPTION "捷徑" FONT 9, "新細明體", 0, 0, 0x0 BEGIN ICON "", IDC_SHORTCUT_ICON, 8, 8, 21, 20, WS_VISIBLE EDITTEXT IDC_SHORTCUT_TEXT, 49, 10, 180, 14, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL LTEXT "", -1, 8, 31, 223, 1, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE - LTEXT "Target type:", IDC_SHORTCUT_TYPE, 8, 38, 68, 10 + LTEXT "目標類型:", IDC_SHORTCUT_TYPE, 8, 38, 68, 10 EDITTEXT IDC_SHORTCUT_TYPE_EDIT, 79, 37, 150, 12, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL - LTEXT "Target location:", IDC_SHORTCUT_LOCATION, 8, 55, 68, 10 + LTEXT "目標位置:", IDC_SHORTCUT_LOCATION, 8, 55, 68, 10 EDITTEXT IDC_SHORTCUT_LOCATION_EDIT, 79, 53, 150, 12, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL - LTEXT "&Target:", IDC_SHORTCUT_TARGET, 8, 71, 68, 10 + LTEXT "目標(&T):", IDC_SHORTCUT_TARGET, 8, 71, 68, 10 EDITTEXT IDC_SHORTCUT_TARGET_TEXT, 79, 69, 150, 14, ES_AUTOHSCROLL LTEXT "", -1, 8, 88, 223, 1, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE - LTEXT "&Start in:", IDC_SHORTCUT_START_IN, 8, 98, 68, 10 + LTEXT "開始位置(&S):", IDC_SHORTCUT_START_IN, 8, 98, 68, 10 EDITTEXT IDC_SHORTCUT_START_IN_EDIT, 79, 96, 150, 14, ES_AUTOHSCROLL - LTEXT "Shortcut &key:", IDC_SHORTCUT_KEY, 8, 117, 68, 10 + LTEXT "快速鍵(&K):", IDC_SHORTCUT_KEY, 8, 117, 68, 10 CONTROL "", IDC_SHORTCUT_KEY_HOTKEY, "msctls_hotkey32", WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP, 79, 115, 150, 14 - LTEXT "&Run:", IDC_SHORTCUT_RUN, 8, 136, 68, 10 + LTEXT "執行(&R):", IDC_SHORTCUT_RUN, 8, 136, 68, 10 COMBOBOX IDC_SHORTCUT_RUN_COMBO, 79, 134, 150, 14, CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP - LTEXT "C&omment:", IDC_SHORTCUT_COMMENT, 8, 154, 68, 10 + LTEXT "註解(&O):", IDC_SHORTCUT_COMMENT, 8, 154, 68, 10 EDITTEXT IDC_SHORTCUT_COMMENT_EDIT, 79, 152, 150, 14, ES_AUTOHSCROLL - PUSHBUTTON "&Find Target...", IDC_SHORTCUT_FIND, 9, 172, 70, 14, ES_LEFT - PUSHBUTTON "&Change Icon...", IDC_SHORTCUT_CHANGE_ICON, 84, 172, 70, 14, ES_LEFT - PUSHBUTTON "A&dvanced...", IDC_SHORTCUT_ADVANCED, 159, 172, 70, 14, ES_LEFT + PUSHBUTTON "尋找目標(&F)...", IDC_SHORTCUT_FIND, 9, 172, 70, 14, ES_LEFT + PUSHBUTTON "更改圖示(&C)...", IDC_SHORTCUT_CHANGE_ICON, 84, 172, 70, 14, ES_LEFT + PUSHBUTTON "進階(&D)...", IDC_SHORTCUT_ADVANCED, 159, 172, 70, 14, ES_LEFT END IDD_SHORTCUT_EXTENDED_PROPERTIES DIALOGEX 0, 0, 230, 150 @@ -227,7 +228,7 @@ END IDD_FOLDER_PROPERTIES DIALOGEX 0, 0, 240, 205 STYLE DS_SHELLFONT | WS_CHILD | WS_CAPTION -CAPTION "General" +CAPTION "一般" FONT 9, "新細明體", 0, 0, 0x0 BEGIN ICON "", 14000, 16, 7, 32, 32, WS_VISIBLE @@ -256,43 +257,43 @@ END IDD_FILE_PROPERTIES DIALOGEX 0, 0, 240, 205 STYLE DS_SHELLFONT | WS_CHILD | WS_CAPTION -CAPTION "General" +CAPTION "一般" FONT 9, "新細明體", 0, 0, 0x0 BEGIN ICON "", 14000, 16, 7, 32, 32, WS_VISIBLE EDITTEXT 14001, 58, 9, 170, 14, ES_LEFT | WS_TABSTOP LTEXT "", -1, 8, 29, 221, 1, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE - LTEXT "Type of file:", 14004, 8, 35, 50, 10 - CONTROL "File", 14005, "edit", ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP, 58, 35, 170, 10 - LTEXT "Opens with:", 14006, 8, 53, 50, 10 + LTEXT "檔案類型:", 14004, 8, 35, 50, 10 + CONTROL "檔案", 14005, "edit", ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP, 58, 35, 170, 10 + LTEXT "開啟檔案:", 14006, 8, 53, 50, 10 ICON "", 14025, 58, 52, 11, 10, NOT WS_VISIBLE - PUSHBUTTON "&Change...", 14024, 168, 50, 60, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "更改(&C)...", 14024, 168, 50, 60, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP EDITTEXT 14007, 58, 53, 100, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | ES_AUTOHSCROLL | NOT WS_TABSTOP LTEXT "", -1, 8, 68, 221, 1, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE - LTEXT "Location:", 14008, 8, 75, 45, 10 + LTEXT "位置:", 14008, 8, 75, 45, 10 EDITTEXT 14009, 58, 75, 170, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | ES_AUTOHSCROLL | NOT WS_TABSTOP - LTEXT "Size:", 14010, 8, 91, 45, 10 + LTEXT "大小:", 14010, 8, 91, 45, 10 EDITTEXT 14011, 58, 91, 170, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - LTEXT "Size on disk:", 140112, 8, 107, 55, 10 + LTEXT "磁碟大小:", 140112, 8, 107, 55, 10 EDITTEXT 14012, 58, 107, 170, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP LTEXT "", -1, 8, 123, 221, 1, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE - LTEXT "Created:", 14014, 8, 131, 45, 10 + LTEXT "建立日期:", 14014, 8, 131, 45, 10 EDITTEXT 14015, 58, 131, 170, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - LTEXT "Modified:", 14016, 8, 147, 45, 10 + LTEXT "修改日期:", 14016, 8, 147, 45, 10 EDITTEXT 14017, 58, 147, 170, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP - LTEXT "Accessed:", 14018, 8, 163, 45, 10 + LTEXT "存取日期:", 14018, 8, 163, 45, 10 EDITTEXT 14019, 58, 163, 170, 10, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP LTEXT "", -1, 8, 179, 221, 1, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE - LTEXT "Attributes:", 14020, 8, 189, 45, 10 - AUTOCHECKBOX "&Read-only", 14021, 58, 188, 67, 10 - AUTOCHECKBOX "&Hidden", 14022, 126, 188, 50, 10 - AUTOCHECKBOX "&Archive", 14023, 181, 188, 49, 10 - PUSHBUTTON "A&dvanced...", 14028, 180, 185, 50, 15, WS_TABSTOP + LTEXT "屬性:", 14020, 8, 189, 45, 10 + AUTOCHECKBOX "唯讀(&R)", 14021, 58, 188, 67, 10 + AUTOCHECKBOX "隱藏(&H)", 14022, 126, 188, 50, 10 + AUTOCHECKBOX "封存(&A)", 14023, 181, 188, 49, 10 + PUSHBUTTON "進階(&D)...", 14028, 180, 185, 50, 15, WS_TABSTOP END IDD_FILE_VERSION DIALOGEX 0, 0, 235, 215 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Version" +CAPTION "版本" FONT 9, "新細明體", 0, 0, 0x0 BEGIN LTEXT "File version: ", 14000, 10, 10, 55, 10 @@ -310,7 +311,7 @@ END IDD_DRIVE_PROPERTIES DIALOGEX 0, 0, 240, 230 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "General" +CAPTION "一般" FONT 9, "新細明體", 0, 0, 0x0 BEGIN ICON "", 14016, 10, 9, 32, 32, WS_VISIBLE @@ -343,17 +344,17 @@ END IDD_DRIVE_TOOLS DIALOGEX 0, 0, 240, 230 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Tools" +CAPTION "工具" FONT 9, "新細明體", 0, 0, 0x0 BEGIN - GROUPBOX "Error-checking", -1, 5, 5, 230, 60 + GROUPBOX "檢查錯誤", -1, 5, 5, 230, 60 ICON IDI_SHELL_TOOLS_CHKDSK, IDC_STATIC, 13, 25, 21, 20 LTEXT "This option will check the volume for\nerrors.", -1, 40, 25, 160, 20 - PUSHBUTTON "Check Now...", 14000, 130, 45, 90, 15, WS_TABSTOP - GROUPBOX "Defragmentation", -1, 5, 65, 230, 60 + PUSHBUTTON "現在檢查...", 14000, 130, 45, 90, 15, WS_TABSTOP + GROUPBOX "磁碟重組", -1, 5, 65, 230, 60 ICON IDI_SHELL_TOOLS_DEFRAG, IDC_STATIC, 13, 85, 21, 20 - LTEXT "This option will defragment files on the volume", -1, 40, 85, 160, 20 - PUSHBUTTON "Defragment Now...", 14001, 130, 105, 90, 15, WS_TABSTOP + LTEXT "這個選項將會重組磁碟上的檔案。", -1, 40, 85, 160, 20 + PUSHBUTTON "現在重組...", 14001, 130, 105, 90, 15, WS_TABSTOP GROUPBOX "Backup", -1, 5, 130, 230, 60 ICON IDI_SHELL_TOOLS_BACKUP, IDC_STATIC, 13, 150, 21, 20 LTEXT "This option will back up files on the volume.", -1, 40, 150, 160, 20 @@ -441,7 +442,7 @@ END IDD_FOLDER_OPTIONS_VIEW DIALOGEX 0, 0, 264, 256 STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION -CAPTION "View" +CAPTION "檢視" FONT 9, "新細明體", 0, 0, 0x0 BEGIN GROUPBOX "Folder views", -1, 7, 10, 249, 60 @@ -456,7 +457,7 @@ END IDD_FOLDER_OPTIONS_FILETYPES DIALOGEX 0, 0, 264, 256 STYLE DS_SHELLFONT | WS_POPUP | WS_CAPTION -CAPTION "File Types" +CAPTION "檔案類型" FONT 9, "新細明體", 0, 0, 0x0 BEGIN LTEXT "Registered file &types:", -1, 7, 10, 70, 10 @@ -495,13 +496,13 @@ END IDD_LOG_OFF DIALOGEX 0, 0, 188, 60 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUPWINDOW | WS_CAPTION -CAPTION "Log Off ReactOS" +CAPTION "登出 ReactOS" FONT 9, "新細明體" BEGIN ICON IDI_SHELL_LOGOFF, IDC_STATIC, 8, 6, 21, 20 - LTEXT "Are you sure you want to log off?", -1, 49, 15, 131, 8 - DEFPUSHBUTTON "&Log Off", IDOK, 49, 38, 43, 14 - PUSHBUTTON "Cancel", IDCANCEL, 99, 38, 43, 14 + LTEXT "您確定要登出 ReactOS 嗎?", -1, 49, 15, 131, 8 + DEFPUSHBUTTON "登出(&L)", IDOK, 49, 38, 43, 14 + PUSHBUTTON "取消", IDCANCEL, 99, 38, 43, 14 END IDD_DISCONNECT DIALOGEX 0, 0, 188, 60 @@ -612,9 +613,9 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUPWINDOW | WS_VISIBL CAPTION "檢查磁碟" FONT 9, "新細明體" BEGIN - DEFPUSHBUTTON "Start", IDOK, 63, 95, 60, 14 - GROUPBOX "Check disk options", -1, 7, 6, 179, 40 - PUSHBUTTON "Cancel", IDCANCEL, 128, 95, 60, 14 + DEFPUSHBUTTON "開始", IDOK, 63, 95, 60, 14 + GROUPBOX "檢查磁碟選項", -1, 7, 6, 179, 40 + PUSHBUTTON "取消", IDCANCEL, 128, 95, 60, 14 AUTOCHECKBOX "Automatically fix file system errors", 14000, 12, 15, 155, 10 AUTOCHECKBOX "&Scan for and attempt recovery of bad sectors", 14001, 16, 30, 165, 10 CONTROL "", 14002, "MSCTLS_PROGRESS32", 16, 7, 50, 179, 8 @@ -623,7 +624,7 @@ END IDD_PICK_ICON DIALOGEX 0, 0, 193, 200 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION -CAPTION "Change Icon" +CAPTION "更改圖示" FONT 9, "新細明體", 400, 0, 0x1 BEGIN LTEXT "Look for icons in this file:", -1, 7, 7, 179, 10 @@ -792,9 +793,9 @@ BEGIN IDS_OVERWRITEFILE_CAPTION "Confirm File Overwrite" IDS_OVERWRITEFOLDER_TEXT "This folder already contains a folder named '%1'.\n\nIf the files in the destination folder have the same names as files in the\nselected folder they will be replaced. Do you still want to move or copy\nthe folder?" - IDS_FILEOOP_COPYING "Copying..." - IDS_FILEOOP_MOVING "Moving..." - IDS_FILEOOP_DELETING "Deleting..." + IDS_FILEOOP_COPYING "正在複製..." + IDS_FILEOOP_MOVING "正在移動..." + IDS_FILEOOP_DELETING "正在刪除..." IDS_FILEOOP_FROM_TO "From %1 to %2" IDS_FILEOOP_FROM "From %1" IDS_FILEOOP_PREFLIGHT "Preflight"
5 years, 10 months
1
0
0
0
[reactos] 02/02: [FLOPPY_NEW] Import the floppy driver from MS GitHub repository
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e2277b1f0286bf6a5b552…
commit e2277b1f0286bf6a5b5528bdde372ce07bd27d7f Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Sat Dec 15 20:02:03 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Sat Dec 15 20:04:00 2018 +0100 [FLOPPY_NEW] Import the floppy driver from MS GitHub repository Do not enable it yet, as it doesn't work in ROS for the moment :-(. Its place in tree is not optimal (it should be with disk/class/etc.), but I prefer keeping it close to actual driver for now. All the work has been done so that it compiles and links with ReactOS SDK though. --- drivers/storage/floppy_new/CMakeLists.txt | 9 + drivers/storage/floppy_new/floppy.c | 3574 +++++++++++++++++++++++++++++ drivers/storage/floppy_new/floppy.rc | 13 + drivers/storage/floppy_new/floppy_reg.inf | 7 + drivers/storage/floppy_new/guid.c | 11 + media/doc/README.FSD | 3 +- 6 files changed, 3616 insertions(+), 1 deletion(-) diff --git a/drivers/storage/floppy_new/CMakeLists.txt b/drivers/storage/floppy_new/CMakeLists.txt new file mode 100644 index 0000000000..154e553c32 --- /dev/null +++ b/drivers/storage/floppy_new/CMakeLists.txt @@ -0,0 +1,9 @@ +list(APPEND SOURCE + guid.c + floppy.c) + +add_library(floppy SHARED ${SOURCE} floppy.rc) +set_module_type(floppy kernelmodedriver) +add_importlibs(floppy classpnp hal ntoskrnl) +add_cd_file(TARGET floppy DESTINATION reactos/system32/drivers NO_CAB FOR all) +add_registry_inf(floppy_reg.inf) diff --git a/drivers/storage/floppy_new/floppy.c b/drivers/storage/floppy_new/floppy.c new file mode 100644 index 0000000000..3c9a1ebf9c --- /dev/null +++ b/drivers/storage/floppy_new/floppy.c @@ -0,0 +1,3574 @@ +/*++ + +Copyright (C) Microsoft Corporation, 1991 - 1999 + +Module Name: + + floppy.c + +Abstract: + + SCSI floppy class driver + +Author: + + Jeff Havens (jhavens) + +Environment: + + kernel mode only + +Notes: + +Revision History: +02/28/96 georgioc Merged this code with code developed by compaq in + parallel with microsoft, for 120MB floppy support. + +01/17/96 georgioc Made code PNP aware (uses the new \storage\classpnp/scsiport) + +--*/ + +#ifdef _MSC_VER +#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int +#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union +#endif + +#include <stddef.h> +#include <ntddk.h> +#ifndef __REACTOS__ +#include <winerror.h> +#endif +#include <scsi.h> +#include <classpnp.h> +#include <initguid.h> +#include <ntddstor.h> + +#include <ntstrsafe.h> +#include <intsafe.h> + +#define MODE_DATA_SIZE 192 +#define SCSI_FLOPPY_TIMEOUT 20 +#define SFLOPPY_SRB_LIST_SIZE 4 +// +// Define all possible drive/media combinations, given drives listed above +// and media types in ntdddisk.h. +// +// These values are used to index the DriveMediaConstants table. +// + +#define NUMBER_OF_DRIVE_TYPES 7 +#define DRIVE_TYPE_120M 4 //120MB Floptical +#define DRIVE_TYPE_NONE NUMBER_OF_DRIVE_TYPES + +// +// This array describes all media types we support. +// It should be arranged in the increasing order of density +// +// For a given drive, we list all the mediatypes that will +// work with that drive. For instance, a 120MB drive will +// take 720KB media, 1.44MB media, and 120MB media. +// +// Note that, DriveMediaConstants given below is grouped +// as drive and media combination +// +typedef enum _DRIVE_MEDIA_TYPE { + Drive360Media160, // 5.25" 360k drive; 160k media + Drive360Media180, // 5.25" 360k drive; 180k media + Drive360Media320, // 5.25" 360k drive; 320k media + Drive360Media32X, // 5.25" 360k drive; 320k 1k secs + Drive360Media360, // 5.25" 360k drive; 360k media + Drive720Media720, // 3.5" 720k drive; 720k media + Drive120Media160, // 5.25" 1.2Mb drive; 160k media + Drive120Media180, // 5.25" 1.2Mb drive; 180k media + Drive120Media320, // 5.25" 1.2Mb drive; 320k media + Drive120Media32X, // 5.25" 1.2Mb drive; 320k 1k secs + Drive120Media360, // 5.25" 1.2Mb drive; 360k media + Drive120Media120, // 5.25" 1.2Mb drive; 1.2Mb media + Drive144Media720, // 3.5" 1.44Mb drive; 720k media + Drive144Media144, // 3.5" 1.44Mb drive; 1.44Mb media + Drive288Media720, // 3.5" 2.88Mb drive; 720k media + Drive288Media144, // 3.5" 2.88Mb drive; 1.44Mb media + Drive288Media288, // 3.5" 2.88Mb drive; 2.88Mb media + Drive2080Media720, // 3.5" 20.8Mb drive; 720k media + Drive2080Media144, // 3.5" 20.8Mb drive; 1.44Mb media + Drive2080Media2080, // 3.5" 20.8Mb drive; 20.8Mb media + Drive32MMedia32M, // 3.5" 32Mb drive; 32MB media + Drive120MMedia720, // 3.5" 120Mb drive; 720k media + Drive120MMedia144, // 3.5" 120Mb drive; 1.44Mb media + Drive120MMedia120M, // 3.5" 120Mb drive; 120Mb media + Drive240MMedia144M, // 3.5" 240Mb drive; 1.44Mb media + Drive240MMedia120M, // 3.5" 240Mb drive; 120Mb media + Drive240MMedia240M // 3.5" 240Mb drive; 240Mb media +} DRIVE_MEDIA_TYPE; + +// +// When we want to determine the media type in a drive, we will first +// guess that the media with highest possible density is in the drive, +// and keep trying lower densities until we can successfully read from +// the drive. +// +// These values are used to select a DRIVE_MEDIA_TYPE value. +// +// The following table defines ranges that apply to the DRIVE_MEDIA_TYPE +// enumerated values when trying media types for a particular drive type. +// Note that for this to work, the DRIVE_MEDIA_TYPE values must be sorted +// by ascending densities within drive types. Also, for maximum track +// size to be determined properly, the drive types must be in ascending +// order. +// + +typedef struct _DRIVE_MEDIA_LIMITS { + DRIVE_MEDIA_TYPE HighestDriveMediaType; + DRIVE_MEDIA_TYPE LowestDriveMediaType; +} DRIVE_MEDIA_LIMITS, *PDRIVE_MEDIA_LIMITS; + +#if 0 +DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = { + + { Drive360Media360, Drive360Media160 }, // DRIVE_TYPE_0360 + { Drive120Media120, Drive120Media160 }, // DRIVE_TYPE_1200 + { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720 + { Drive144Media144, Drive144Media720 }, // DRIVE_TYPE_1440 + { Drive288Media288, Drive288Media720 }, // DRIVE_TYPE_2880 + { Drive2080Media2080, Drive2080Media720 } +}; +#else +DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = { + + { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720 + { Drive144Media144, Drive144Media720}, // DRIVE_TYPE_1440 + { Drive288Media288, Drive288Media720}, // DRIVE_TYPE_2880 + { Drive2080Media2080, Drive2080Media720 }, + { Drive32MMedia32M, Drive32MMedia32M }, // DRIVE_TYPE_32M + { Drive120MMedia120M, Drive120MMedia720 }, // DRIVE_TYPE_120M + { Drive240MMedia240M, Drive240MMedia144M } // DRIVE_TYPE_240M +}; + +#endif +// +// For each drive/media combination, define important constants. +// + +typedef struct _DRIVE_MEDIA_CONSTANTS { + MEDIA_TYPE MediaType; + USHORT BytesPerSector; + UCHAR SectorsPerTrack; + USHORT MaximumTrack; + UCHAR NumberOfHeads; +} DRIVE_MEDIA_CONSTANTS, *PDRIVE_MEDIA_CONSTANTS; + +// +// Magic value to add to the SectorLengthCode to use it as a shift value +// to determine the sector size. +// + +#define SECTORLENGTHCODE_TO_BYTESHIFT 7 + +// +// The following values were gleaned from many different sources, which +// often disagreed with each other. Where numbers were in conflict, I +// chose the more conservative or most-often-selected value. +// + +DRIVE_MEDIA_CONSTANTS DriveMediaConstants[] = + { + + { F5_160_512, 0x200, 0x08, 0x27, 0x1 }, + { F5_180_512, 0x200, 0x09, 0x27, 0x1 }, + { F5_320_1024, 0x400, 0x04, 0x27, 0x2 }, + { F5_320_512, 0x200, 0x08, 0x27, 0x2 }, + { F5_360_512, 0x200, 0x09, 0x27, 0x2 }, + + { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, + + { F5_160_512, 0x200, 0x08, 0x27, 0x1 }, + { F5_180_512, 0x200, 0x09, 0x27, 0x1 }, + { F5_320_1024, 0x400, 0x04, 0x27, 0x2 }, + { F5_320_512, 0x200, 0x08, 0x27, 0x2 }, + { F5_360_512, 0x200, 0x09, 0x27, 0x2 }, + { F5_1Pt2_512, 0x200, 0x0f, 0x4f, 0x2 }, + + { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, + { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, + + { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, + { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, + { F3_2Pt88_512, 0x200, 0x24, 0x4f, 0x2 }, + + { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, + { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, + { F3_20Pt8_512, 0x200, 0x1b, 0xfa, 0x6 }, + + { F3_32M_512, 0x200, 0x20, 0x3ff,0x2}, + + { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, + { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, + { F3_120M_512, 0x200, 0x20, 0x3c2,0x8 }, + + { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, + { F3_120M_512, 0x200, 0x20, 0x3c2,0x8 }, + { F3_240M_512, 0x200, 0x38, 0x105,0x20} +}; + + +#define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS sizeof(DriveMediaConstants)/sizeof(DRIVE_MEDIA_CONSTANTS) + +// +// floppy device data +// + +typedef struct _DISK_DATA { + ULONG DriveType; + BOOLEAN IsDMF; + // BOOLEAN EnableDMF; + UNICODE_STRING FloppyInterfaceString; +} DISK_DATA, *PDISK_DATA; + +// +// The FloppyCapacities and FloppyGeometries arrays are used by the +// USBFlopGetMediaTypes() and USBFlopFormatTracks() routines. + +// The FloppyCapacities and FloppyGeometries arrays must be kept in 1:1 sync, +// i.e. each FloppyGeometries[i] must correspond to each FloppyCapacities[i]. + +// Also, the arrays must be kept in sorted ascending order so that they +// are returned in sorted ascending order by IOCTL_DISK_GET_MEDIA_TYPES. +// + +typedef struct _FORMATTED_CAPACITY +{ + ULONG NumberOfBlocks; + + ULONG BlockLength; + + BOOLEAN CanFormat; // return for IOCTL_DISK_GET_MEDIA_TYPES ? + +} FORMATTED_CAPACITY, *PFORMATTED_CAPACITY; + + +FORMATTED_CAPACITY FloppyCapacities[] = +{ + // Blocks BlockLen CanFormat H T B/S S/T + {0x000500, 0x0200, TRUE}, // 2 80 512 8 640 KB F5_640_512 + {0x0005A0, 0x0200, TRUE}, // 2 80 512 9 720 KB F3_720_512 + {0x000960, 0x0200, TRUE}, // 2 80 512 15 1.20 MB F3_1Pt2_512 (Toshiba) + {0x0004D0, 0x0400, TRUE}, // 2 77 1024 8 1.23 MB F3_1Pt23_1024 (NEC) + {0x000B40, 0x0200, TRUE}, // 2 80 512 18 1.44 MB F3_1Pt44_512 + {0x000D20, 0x0200, FALSE}, // 2 80 512 21 1.70 MB DMF + {0x010000, 0x0200, TRUE}, // 2 1024 512 32 32 MB F3_32M_512 + {0x03C300, 0x0200, TRUE}, // 8 963 512 32 120 MB F3_120M_512 + {0x0600A4, 0x0200, TRUE}, // 13 890 512 34 200 MB F3_200Mb_512 (HiFD) + {0x072A00, 0x0200, TRUE} // 32 262 512 56 240 MB F3_240M_512 +}; + +DISK_GEOMETRY FloppyGeometries[] = +{ + // Cyl MediaType Trk/Cyl Sec/Trk Bytes/Sec +#ifndef __REACTOS__ + {{80,0}, F3_640_512, 2, 8, 512}, + {{80,0}, F3_720_512, 2, 9, 512}, + {{80,0}, F3_1Pt2_512, 2, 15, 512}, + {{77,0}, F3_1Pt23_1024, 2, 8, 1024}, + {{80,0}, F3_1Pt44_512, 2, 18, 512}, + {{80,0}, F3_1Pt44_512, 2, 21, 512}, // DMF -> F3_1Pt44_512 + {{1024,0}, F3_32M_512, 2, 32, 512}, + {{963,0}, F3_120M_512, 8, 32, 512}, + {{890,0}, F3_200Mb_512, 13, 34, 512}, + {{262,0}, F3_240M_512, 32, 56, 512} +#else + {{.LowPart = 80, .HighPart = 0}, F3_640_512, 2, 8, 512}, + {{.LowPart = 80, .HighPart = 0}, F3_720_512, 2, 9, 512}, + {{.LowPart = 80, .HighPart = 0}, F3_1Pt2_512, 2, 15, 512}, + {{.LowPart = 77, .HighPart = 0}, F3_1Pt23_1024, 2, 8, 1024}, + {{.LowPart = 80, .HighPart = 0}, F3_1Pt44_512, 2, 18, 512}, + {{.LowPart = 80, .HighPart = 0}, F3_1Pt44_512, 2, 21, 512}, // DMF -> F3_1Pt44_512 + {{.LowPart = 1024, .HighPart = 0}, F3_32M_512, 2, 32, 512}, + {{.LowPart = 963, .HighPart = 0}, F3_120M_512, 8, 32, 512}, + {{.LowPart = 890, .HighPart = 0}, F3_200Mb_512, 13, 34, 512}, + {{.LowPart = 262, .HighPart = 0}, F3_240M_512, 32, 56, 512} +#endif +}; + +#define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0])) + +C_ASSERT((sizeof(FloppyGeometries)/sizeof(FloppyGeometries[0])) == FLOPPY_CAPACITIES); + +// +// The following structures are used by USBFlopFormatTracks() +// + +#pragma pack (push, 1) + +typedef struct _CDB12FORMAT +{ + UCHAR OperationCode; + UCHAR DefectListFormat : 3; + UCHAR CmpList : 1; + UCHAR FmtData : 1; + UCHAR LogicalUnitNumber : 3; + UCHAR TrackNumber; + UCHAR InterleaveMsb; + UCHAR InterleaveLsb; + UCHAR Reserved1[2]; + UCHAR ParameterListLengthMsb; + UCHAR ParameterListLengthLsb; + UCHAR Reserved2[3]; +} CDB12FORMAT, *PCDB12FORMAT; + + +typedef struct _DEFECT_LIST_HEADER +{ + UCHAR Reserved1; + UCHAR Side : 1; + UCHAR Immediate : 1; + UCHAR Reserved2 : 2; + UCHAR SingleTrack : 1; + UCHAR DisableCert : 1; + UCHAR Reserved3 : 1; + UCHAR FormatOptionsValid : 1; + UCHAR DefectListLengthMsb; + UCHAR DefectListLengthLsb; +} DEFECT_LIST_HEADER, *PDEFECT_LIST_HEADER; + +typedef struct _FORMAT_UNIT_PARAMETER_LIST +{ + DEFECT_LIST_HEADER DefectListHeader; + FORMATTED_CAPACITY_DESCRIPTOR FormatDescriptor; +} FORMAT_UNIT_PARAMETER_LIST, *PFORMAT_UNIT_PARAMETER_LIST; + +#pragma pack (pop) + +DRIVER_INITIALIZE DriverEntry; + +DRIVER_UNLOAD ScsiFlopUnload; + +DRIVER_ADD_DEVICE ScsiFlopAddDevice; + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopInitDevice( + IN PDEVICE_OBJECT Fdo + ); + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopStartDevice( + IN PDEVICE_OBJECT Fdo + ); + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopRemoveDevice( + IN PDEVICE_OBJECT Fdo, + IN UCHAR Type + ); + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopStopDevice( + IN PDEVICE_OBJECT Fdo, + IN UCHAR Type + ); + +BOOLEAN +FindScsiFlops( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN PCLASS_INIT_DATA InitializationData, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber + ); + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopReadWriteVerification( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +BOOLEAN +IsFloppyDevice( + PDEVICE_OBJECT DeviceObject + ); + +NTSTATUS +CreateFlopDeviceObject( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG DeviceCount + ); + +NTSTATUS +DetermineMediaType( + PDEVICE_OBJECT DeviceObject + ); + +ULONG +DetermineDriveType( + PDEVICE_OBJECT DeviceObject + ); + +BOOLEAN +FlCheckFormatParameters( + IN PDEVICE_OBJECT DeviceObject, + IN PFORMAT_PARAMETERS FormatParameters + ); + +NTSTATUS +FormatMedia( + PDEVICE_OBJECT DeviceObject, + MEDIA_TYPE MediaType + ); + +NTSTATUS +FlopticalFormatMedia( + PDEVICE_OBJECT DeviceObject, + PFORMAT_PARAMETERS Format + ); + +VOID +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopProcessError( + PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + NTSTATUS *Status, + BOOLEAN *Retry + ); + +NTSTATUS +USBFlopGetMediaTypes( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +USBFlopFormatTracks( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, DriverEntry) + +#pragma alloc_text(PAGE, ScsiFlopUnload) +#pragma alloc_text(PAGE, ScsiFlopAddDevice) +#pragma alloc_text(PAGE, CreateFlopDeviceObject) +#pragma alloc_text(PAGE, ScsiFlopStartDevice) +#pragma alloc_text(PAGE, ScsiFlopRemoveDevice) +#pragma alloc_text(PAGE, IsFloppyDevice) +#pragma alloc_text(PAGE, DetermineMediaType) +#pragma alloc_text(PAGE, DetermineDriveType) +#pragma alloc_text(PAGE, FlCheckFormatParameters) +#pragma alloc_text(PAGE, FormatMedia) +#pragma alloc_text(PAGE, FlopticalFormatMedia) +#pragma alloc_text(PAGE, USBFlopGetMediaTypes) +#pragma alloc_text(PAGE, USBFlopFormatTracks) + +#endif + + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + This is the system initialization routine for installable drivers. + It calls the SCSI class driver initialization routine. + +Arguments: + + DriverObject - Pointer to driver object created by system. + +Return Value: + + NTSTATUS + +--*/ + +{ + CLASS_INIT_DATA InitializationData; + + // + // Zero InitData + // + + RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA)); + + // + // Set sizes + // + + InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA); + InitializationData.FdoData.DeviceExtensionSize = + sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA); + + InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK; + InitializationData.FdoData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE; + + // + // Set entry points + // + + InitializationData.FdoData.ClassInitDevice = ScsiFlopInitDevice; + InitializationData.FdoData.ClassStartDevice = ScsiFlopStartDevice; + InitializationData.FdoData.ClassStopDevice = ScsiFlopStopDevice; + InitializationData.FdoData.ClassRemoveDevice = ScsiFlopRemoveDevice; + + InitializationData.FdoData.ClassReadWriteVerification = ScsiFlopReadWriteVerification; + InitializationData.FdoData.ClassDeviceControl = ScsiFlopDeviceControl; + + InitializationData.FdoData.ClassShutdownFlush = NULL; + InitializationData.FdoData.ClassCreateClose = NULL; + InitializationData.FdoData.ClassError = ScsiFlopProcessError; + InitializationData.ClassStartIo = NULL; + + InitializationData.ClassAddDevice = ScsiFlopAddDevice; + InitializationData.ClassUnload = ScsiFlopUnload; + // + // Call the class init routine + // + + return ClassInitialize( DriverObject, RegistryPath, &InitializationData); + + +} // end DriverEntry() + +VOID +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopUnload( + IN PDRIVER_OBJECT DriverObject + ) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(DriverObject); + return; +} + +// +// AddDevice operation is performed in CreateFlopDeviceObject function which +// is called by ScsiFlopAddDevice (The AddDevice routine for sfloppy.sys). +// DO_DEVICE_INITIALIZING flag is cleard upon successfully processing AddDevice +// operation in CreateFlopDeviceObject. But PREFAST is currently unable to +// detect that DO_DEVICE_INITIALIZING is indeed cleard in CreateFlopDeviceObject +// and it raises Warning 28152 (The return from an AddDevice-like function +// unexpectedly did not clear DO_DEVICE_INITIALIZING). Suppress that warning +// using #pragma. +// + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:28152) +#endif + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopAddDevice ( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo + ) +/*++ + +Routine Description: + + This routine creates and initializes a new FDO for the corresponding + PDO. It may perform property queries on the FDO but cannot do any + media access operations. + +Arguments: + + DriverObject - Scsiscan class driver object. + + Pdo - the physical device object we are being added to + +Return Value: + + status + +--*/ +{ + NTSTATUS status; + ULONG floppyCount = IoGetConfigurationInformation()->FloppyCount; + + PAGED_CODE(); + + // + // Get the number of disks already initialized. + // + + status = CreateFlopDeviceObject(DriverObject, Pdo, floppyCount); + + if (NT_SUCCESS(status)) { + + // + // Increment system floppy device count. + // + + IoGetConfigurationInformation()->FloppyCount++; + } + + return status; +} + +NTSTATUS +CreateFlopDeviceObject( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo, + IN ULONG DeviceCount + ) + +/*++ + +Routine Description: + + This routine creates an object for the device and then calls the + SCSI port driver for media capacity and sector size. + +Arguments: + + DriverObject - Pointer to driver object created by system. + PortDeviceObject - to connect to SCSI port driver. + DeviceCount - Number of previously installed Floppys. + AdapterDescriptor - Pointer to structure returned by SCSI port + driver describing adapter capabilites (and limitations). + DeviceDescriptor - Pointer to configuration information for this device. + +Return Value: + +--*/ +{ + NTSTATUS status; + PDEVICE_OBJECT deviceObject = NULL; + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL; + PDISK_DATA diskData; + + PAGED_CODE(); + + DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n")); + + // + // Try to claim the device. + // + + status = ClassClaimDevice(Pdo,FALSE); + + if (!NT_SUCCESS(status)) { + return(status); + } + + DeviceCount--; + + do { + UCHAR name[256]; + + // + // Create device object for this device. + // + + DeviceCount++; + + status = RtlStringCbPrintfA((PCCHAR) name, + sizeof(name)/sizeof(UCHAR), + "\\Device\\Floppy%u", + DeviceCount); + if (NT_SUCCESS(status)) { + + status = ClassCreateDeviceObject(DriverObject, + (PCCHAR) name, + Pdo, + TRUE, + &deviceObject); + } + } while ((status == STATUS_OBJECT_NAME_COLLISION) || + (status == STATUS_OBJECT_NAME_EXISTS)); + + if (!NT_SUCCESS(status)) { + DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n")); + goto CreateFlopDeviceObjectExit; + } + + // + // Indicate that IRPs should include MDLs. + // + + deviceObject->Flags |= DO_DIRECT_IO; + + fdoExtension = deviceObject->DeviceExtension; + + // + // Back pointer to device object. + // + + fdoExtension->CommonExtension.DeviceObject = deviceObject; + + // + // This is the physical device. + // + + fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension; + + // + // Reset the drive type. + // + + diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; + diskData->DriveType = DRIVE_TYPE_NONE; + diskData->IsDMF = FALSE; + // diskData->EnableDMF = TRUE; + + // + // Initialize lock count to zero. The lock count is used to + // disable the ejection mechanism when media is mounted. + // + + fdoExtension->LockCount = 0; + + // + // Save system floppy number + // + + fdoExtension->DeviceNumber = DeviceCount; + + // + // Set the alignment requirements for the device based on the + // host adapter requirements + // + + if (Pdo->AlignmentRequirement > deviceObject->AlignmentRequirement) { + deviceObject->AlignmentRequirement = Pdo->AlignmentRequirement; + } + + // + // Clear the SrbFlags and disable synchronous transfers + // + + fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + // + // Finally, attach to the PDO + // + + fdoExtension->LowerPdo = Pdo; + + fdoExtension->CommonExtension.LowerDeviceObject = + IoAttachDeviceToDeviceStack(deviceObject, Pdo); + + if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) { + + status = STATUS_UNSUCCESSFUL; + goto CreateFlopDeviceObjectExit; + } + + deviceObject->StackSize++; + + // + // The device is initialized properly - mark it as such. + // + + deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; + +CreateFlopDeviceObjectExit: + + if (deviceObject != NULL) { + IoDeleteDevice(deviceObject); + } + + return status; + +} // end CreateFlopDeviceObject() +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopInitDevice( + IN PDEVICE_OBJECT Fdo + ) +{ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; + PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; + PDISK_DATA diskData = commonExtension->DriverData; + + PVOID senseData = NULL; + ULONG timeOut; + + NTSTATUS status = STATUS_SUCCESS; + + // + // Allocate request sense buffer. + // + +#ifndef __REACTOS__ + senseData = ExAllocatePool(NonPagedPoolNxCacheAligned, SENSE_BUFFER_SIZE); +#else + senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); +#endif + + if (senseData == NULL) { + + // + // The buffer cannot be allocated. + // + + status = STATUS_INSUFFICIENT_RESOURCES; + return status; + } + + // + // Set the sense data pointer in the device extension. + // + + fdoExtension->SenseData = senseData; + + // + // Build the lookaside list for srb's for this device. + // + + ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION)fdoExtension, + SFLOPPY_SRB_LIST_SIZE); + + // + // Register for media change notification + // + ClassInitializeMediaChangeDetection(fdoExtension, + (PUCHAR) "SFloppy"); + + // + // Set timeout value in seconds. + // + + timeOut = ClassQueryTimeOutRegistryValue(Fdo); + if (timeOut) { + fdoExtension->TimeOutValue = timeOut; + } else { + fdoExtension->TimeOutValue = SCSI_FLOPPY_TIMEOUT; + } + + // + // Floppies are not partitionable so starting offset is 0. + // + + fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)0; + +#if 0 + if (!IsFloppyDevice(Fdo) || + !(Fdo->Characteristics & FILE_REMOVABLE_MEDIA) || + (fdoExtension->DeviceDescriptor->DeviceType != DIRECT_ACCESS_DEVICE)) { + + ExFreePool(senseData); + status = STATUS_NO_SUCH_DEVICE; + return status; + } +#endif + + RtlZeroMemory(&(fdoExtension->DiskGeometry), + sizeof(DISK_GEOMETRY)); + + // + // Determine the media type if possible. Set the current media type to + // Unknown so that determine media type will check the media. + // + + fdoExtension->DiskGeometry.MediaType = Unknown; + + // + // Register interfaces for this device. + // + + { + UNICODE_STRING interfaceName; + + RtlInitUnicodeString(&interfaceName, NULL); + + status = IoRegisterDeviceInterface(fdoExtension->LowerPdo, + (LPGUID) &GUID_DEVINTERFACE_FLOPPY, + NULL, + &interfaceName); + + if(NT_SUCCESS(status)) { + diskData->FloppyInterfaceString = interfaceName; + } else { + RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL); + DebugPrint((1, "ScsiFlopStartDevice: Unable to register device " + "interface for fdo %p [%08lx]\n", + Fdo, status)); + } + } + + return (STATUS_SUCCESS); +} + +#ifdef _MSC_VER +#pragma warning(suppress:6262) // This function uses 1096 bytes of stack which exceed default value of 1024 bytes used by Code Analysis for flagging as warning +#endif +#ifdef __REACTOS__ +NTSTATUS NTAPI ScsiFlopStartDevice( +#else +NTSTATUS ScsiFlopStartDevice( +#endif + IN PDEVICE_OBJECT Fdo + ) +{ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; + PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; + + PIRP irp; + IO_STATUS_BLOCK ioStatus; + + SCSI_ADDRESS scsiAddress; + + WCHAR ntNameBuffer[256]; + UNICODE_STRING ntUnicodeString; + + WCHAR arcNameBuffer[256]; + UNICODE_STRING arcUnicodeString; + + KEVENT event; + + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + KeInitializeEvent(&event,SynchronizationEvent,FALSE); + + DetermineMediaType(Fdo); // ignore unsuccessful here + + // + // Create device object for this device. + // + + RtlStringCbPrintfW(ntNameBuffer, + sizeof(ntNameBuffer)/sizeof(WCHAR), + L"\\Device\\Floppy%u", + fdoExtension->DeviceNumber); + + // + // Create local copy of unicode string + // + RtlInitUnicodeString(&ntUnicodeString,ntNameBuffer); + + // + // Create a symbolic link from the disk name to the corresponding + // ARC name, to be used if we're booting off the disk. This will + // fail if it's not system initialization time; that's fine. The + // ARC name looks something like \ArcName\scsi(0)Flop(0)fdisk(0). + // In order to get the address, we need to send a IOCTL_SCSI_GET_ADDRESS... + // + + irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS, + Fdo, + NULL, + 0, + &scsiAddress, + sizeof(scsiAddress), + FALSE, + &event, + &ioStatus); + + if (irp == NULL) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); + status = ioStatus.Status; + } + + // + // IOCTL_SCSI_GET_ADDRESS might not be supported by the port driver and + // hence may fail. But it is not a fatal error. Do not fail PnP start + // if this IOCTL fails. + // + if (NT_SUCCESS(status)) { + + RtlStringCbPrintfW(arcNameBuffer, + sizeof(arcNameBuffer)/sizeof(WCHAR), + L"\\ArcName\\scsi(%u)disk(%u)fdisk(%u)", + scsiAddress.PortNumber, + scsiAddress.TargetId, + scsiAddress.Lun); + + RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer); + + IoAssignArcName(&arcUnicodeString, &ntUnicodeString); + } + + status = STATUS_SUCCESS; + + // + // Create the multi() arc name -- Create the "fake" + // name of multi(0)disk(0)fdisk(#) to handle the case where the + // SCSI floppy is the only floppy in the system. If this fails + // it doesn't matter because the previous scsi() based ArcName + // will work. This name is necessary for installation. + // + + RtlStringCbPrintfW(arcNameBuffer, + sizeof(arcNameBuffer)/sizeof(WCHAR), + L"\\ArcName\\multi(%u)disk(%u)fdisk(%u)", + 0, + 0, + fdoExtension->DeviceNumber); + + RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer); + + IoAssignArcName(&arcUnicodeString, &ntUnicodeString); + + // + // Set our interface state. + // + + { + PDISK_DATA diskData = commonExtension->DriverData; + + if(diskData->FloppyInterfaceString.Buffer != NULL) { + + status = IoSetDeviceInterfaceState( + &(diskData->FloppyInterfaceString), + TRUE); + + if(!NT_SUCCESS(status)) { + DebugPrint((1, "ScsiFlopStartDevice: Unable to set device " + "interface state to TRUE for fdo %p " + "[%08lx]\n", + Fdo, status)); + } + } + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopReadWriteVerification( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + + NT Status + +--*/ + +{ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status = STATUS_SUCCESS; + + // + // Make sure that the number of bytes to transfer is a multiple of the sector size + // + if ((irpSp->Parameters.Read.Length & (fdoExtension->DiskGeometry.BytesPerSector - 1)) != 0) + { + status = STATUS_INVALID_PARAMETER; + } + + Irp->IoStatus.Status = status; + + return status; +} + + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + + Status is returned. + +--*/ + +{ + KIRQL currentIrql; + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; + PSCSI_REQUEST_BLOCK srb; + PCDB cdb; + NTSTATUS status; + PDISK_GEOMETRY outputBuffer; + ULONG outputBufferLength; + ULONG i; + DRIVE_MEDIA_TYPE lowestDriveMediaType; + DRIVE_MEDIA_TYPE highestDriveMediaType; + PFORMAT_PARAMETERS formatParameters; + PMODE_PARAMETER_HEADER modeData; + ULONG length; + + // + // Initialize the information field + // + Irp->IoStatus.Information = 0; + +#ifndef __REACTOS__ + srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); +#else + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); +#endif + + if (srb == NULL) { + + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + if (IoIsErrorUserInduced(Irp->IoStatus.Status)) { + + IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); + } + + KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); + ClassReleaseRemoveLock(DeviceObject, Irp); + ClassCompleteRequest(DeviceObject, Irp, 0); + KeLowerIrql(currentIrql); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + // + // Write zeros to Srb. + // + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + cdb = (PCDB)srb->Cdb; + + switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { + + + case IOCTL_DISK_VERIFY: { + + PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer; + LARGE_INTEGER byteOffset; + ULONG sectorOffset; + USHORT sectorCount; + + // + // Validate buffer length. + // + + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < + sizeof(VERIFY_INFORMATION)) { + + status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + // + // Perform a bounds check on the sector range + // + if ((verifyInfo->StartingOffset.QuadPart > fdoExtension->CommonExtension.PartitionLength.QuadPart) || + (verifyInfo->StartingOffset.QuadPart < 0)) + { + status = STATUS_NONEXISTENT_SECTOR; + break; + } + else + { + ULONGLONG bytesRemaining = fdoExtension->CommonExtension.PartitionLength.QuadPart - verifyInfo->StartingOffset.QuadPart; + + if ((ULONGLONG)verifyInfo->Length > bytesRemaining) + { + status = STATUS_NONEXISTENT_SECTOR; + break; + } + } + + // + // Verify sectors + // + + srb->CdbLength = 10; + + cdb->CDB10.OperationCode = SCSIOP_VERIFY; + + // + // Add disk offset to starting sector. + // + + byteOffset.QuadPart = fdoExtension->CommonExtension.StartingOffset.QuadPart + + verifyInfo->StartingOffset.QuadPart; + + // + // Convert byte offset to sector offset. + // + + sectorOffset = (ULONG)(byteOffset.QuadPart >> fdoExtension->SectorShift); + + // + // Convert ULONG byte count to USHORT sector count. + // + + sectorCount = (USHORT)(verifyInfo->Length >> fdoExtension->SectorShift); + + // + // Move little endian values into CDB in big endian format. + // + + cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)§orOffset)->Byte3; + cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)§orOffset)->Byte2; + cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)§orOffset)->Byte1; + cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)§orOffset)->Byte0; + + cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)§orCount)->Byte1; + cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)§orCount)->Byte0; + + // + // The verify command is used by the NT FORMAT utility and + // requests are sent down for 5% of the volume size. The + // request timeout value is calculated based on the number of + // sectors verified. + // + + srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) * + fdoExtension->TimeOutValue; + + status = ClassSendSrbAsynchronous(DeviceObject, + srb, + Irp, + NULL, + 0, + FALSE); + return(status); + + } + + case IOCTL_DISK_GET_PARTITION_INFO: { + + if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) { + + USBFlopGetMediaTypes(DeviceObject, NULL); + + // Don't need to propagate any error if one occurs + // + status = STATUS_SUCCESS; + + } else { + + status = DetermineMediaType(DeviceObject); + } + + if (!NT_SUCCESS(status)) { + // so will propogate error + NOTHING; + } else if (fdoExtension->DiskGeometry.MediaType == F3_120M_512) { + //so that the format code will not try to partition it. + status = STATUS_INVALID_DEVICE_REQUEST; + } else { + // + // Free the Srb, since it is not needed. + // + + ExFreePool(srb); + + // + // Pass the request to the common device control routine. + // + + return(ClassDeviceControl(DeviceObject, Irp)); + } + break; + } + + case IOCTL_DISK_GET_DRIVE_GEOMETRY: { + + DebugPrint((3,"ScsiDeviceIoControl: Get drive geometry\n")); + + if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) + { + status = USBFlopGetMediaTypes(DeviceObject, + Irp); + break; + } + + // + // If there's not enough room to write the + // data, then fail the request. + // + + if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof( DISK_GEOMETRY ) ) { + + status = STATUS_INVALID_PARAMETER; + break; + } + + status = DetermineMediaType(DeviceObject); + + if (!NT_SUCCESS(status)) { + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status; + + } else { + + // + // Copy drive geometry information from device extension. + // + + RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, + &(fdoExtension->DiskGeometry), + sizeof(DISK_GEOMETRY)); + + Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); + status = STATUS_SUCCESS; + + } + + break; + } + + case IOCTL_DISK_GET_MEDIA_TYPES: { + + if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) + { + status = USBFlopGetMediaTypes(DeviceObject, + Irp); + break; + } + + i = DetermineDriveType(DeviceObject); + + if (i == DRIVE_TYPE_NONE) { + status = STATUS_UNRECOGNIZED_MEDIA; + break; + } + + lowestDriveMediaType = DriveMediaLimits[i].LowestDriveMediaType; + highestDriveMediaType = DriveMediaLimits[i].HighestDriveMediaType; + + outputBufferLength = + irpStack->Parameters.DeviceIoControl.OutputBufferLength; + + // + // Make sure that the input buffer has enough room to return + // at least one descriptions of a supported media type. + // + + if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) ) ) { + + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + // + // Assume success, although we might modify it to a buffer + // overflow warning below (if the buffer isn't big enough + // to hold ALL of the media descriptions). + // + + status = STATUS_SUCCESS; + + if (outputBufferLength < ( sizeof( DISK_GEOMETRY ) * + ( highestDriveMediaType - lowestDriveMediaType + 1 ) ) ) { + + // + // The buffer is too small for all of the descriptions; + // calculate what CAN fit in the buffer. + // + + status = STATUS_BUFFER_OVERFLOW; + + highestDriveMediaType = (DRIVE_MEDIA_TYPE)( ( lowestDriveMediaType - 1 ) + + ( outputBufferLength / + sizeof( DISK_GEOMETRY ) ) ); + } + + outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; + + for (i = (UCHAR)lowestDriveMediaType;i <= (UCHAR)highestDriveMediaType;i++ ) { + + outputBuffer->MediaType = DriveMediaConstants[i].MediaType; + outputBuffer->Cylinders.LowPart = + DriveMediaConstants[i].MaximumTrack + 1; + outputBuffer->Cylinders.HighPart = 0; + outputBuffer->TracksPerCylinder = + DriveMediaConstants[i].NumberOfHeads; + outputBuffer->SectorsPerTrack = + DriveMediaConstants[i].SectorsPerTrack; + outputBuffer->BytesPerSector = + DriveMediaConstants[i].BytesPerSector; + outputBuffer++; + + Irp->IoStatus.Information += sizeof( DISK_GEOMETRY ); + } + + break; + } + + case IOCTL_DISK_FORMAT_TRACKS: { + + if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) + { + status = USBFlopFormatTracks(DeviceObject, + Irp); + break; + } + + // + // Make sure that we got all the necessary format parameters. + // + + if ( irpStack->Parameters.DeviceIoControl.InputBufferLength <sizeof( FORMAT_PARAMETERS ) ) { + + status = STATUS_INVALID_PARAMETER; + break; + } + + formatParameters = (PFORMAT_PARAMETERS) Irp->AssociatedIrp.SystemBuffer; + + // + // Make sure the parameters we got are reasonable. + // + + if ( !FlCheckFormatParameters(DeviceObject, formatParameters)) { + + status = STATUS_INVALID_PARAMETER; + break; + } + + // + // If this request is for a 20.8 MB floppy then call a special + // floppy format routine. + // + + if (formatParameters->MediaType == F3_20Pt8_512) { + status = FlopticalFormatMedia(DeviceObject, + formatParameters + ); + + break; + } + + // + // All the work is done in the pass. If this is not the first pass, + // then complete the request and return; + // + + if (formatParameters->StartCylinderNumber != 0 || formatParameters->StartHeadNumber != 0) { + + status = STATUS_SUCCESS; + break; + } + + status = FormatMedia( DeviceObject, formatParameters->MediaType); + break; + } + + case IOCTL_DISK_IS_WRITABLE: { + + if ((fdoExtension->DiskGeometry.MediaType) == F3_32M_512) { + + // + // 32MB media is READ ONLY. Just return + // STATUS_MEDIA_WRITE_PROTECTED + // + + status = STATUS_MEDIA_WRITE_PROTECTED; + + break; + } + + // + // Determine if the device is writable. + // + +#ifndef __REACTOS__ + modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); +#else + modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE); +#endif + + if (modeData == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + RtlZeroMemory(modeData, MODE_DATA_SIZE); + + length = ClassModeSense(DeviceObject, + (PCHAR) modeData, + MODE_DATA_SIZE, + MODE_SENSE_RETURN_ALL); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + + // + // Retry the request in case of a check condition. + // + + length = ClassModeSense(DeviceObject, + (PCHAR) modeData, + MODE_DATA_SIZE, + MODE_SENSE_RETURN_ALL); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + status = STATUS_IO_DEVICE_ERROR; + ExFreePool(modeData); + break; + } + } + + if (modeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT) { + status = STATUS_MEDIA_WRITE_PROTECTED; + } else { + status = STATUS_SUCCESS; + } + + DebugPrint((2,"IOCTL_DISK_IS_WRITABLE returns %08X\n", status)); + + ExFreePool(modeData); + break; + } + + default: { + + DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n")); + + // + // Free the Srb, since it is not needed. + // + + ExFreePool(srb); + + // + // Pass the request to the common device control routine. + // + + return(ClassDeviceControl(DeviceObject, Irp)); + + break; + } + + } // end switch( ... + + // + // Check if SL_OVERRIDE_VERIFY_VOLUME flag is set in the IRP. + // If so, do not return STATUS_VERIFY_REQUIRED + // + if ((status == STATUS_VERIFY_REQUIRED) && + (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))) { + + status = STATUS_IO_DEVICE_ERROR; + + } + + Irp->IoStatus.Status = status; + + if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { + + IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); + } + + KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); + ClassReleaseRemoveLock(DeviceObject, Irp); + ClassCompleteRequest(DeviceObject, Irp, 0); + KeLowerIrql(currentIrql); + + ExFreePool(srb); + + return status; + +} // end ScsiFlopDeviceControl() + +#if 0 + +BOOLEAN +IsFloppyDevice( + PDEVICE_OBJECT DeviceObject + ) +/*++ + +Routine Description: + + The routine performs the necessary funcitons to deterime if the device is + really a floppy rather than a harddisk. This is done by a mode sense + command. First a check is made to see if the medimum type is set. Second + a check is made for the flexible parameters mode page. + +Arguments: + + DeviceObject - Supplies the device object to be tested. + +Return Value: + + Return TRUE if the indicated device is a floppy. + +--*/ +{ + + PVOID modeData; + PUCHAR pageData; + ULONG length; + + modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); + + if (modeData == NULL) { + return(FALSE); + } + + RtlZeroMemory(modeData, MODE_DATA_SIZE); + + length = ClassModeSense(DeviceObject, modeData, MODE_DATA_SIZE, MODE_SENSE_RETURN_ALL); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + + // + // Retry the request in case of a check condition. + // + + length = ClassModeSense(DeviceObject, + modeData, + MODE_DATA_SIZE, + MODE_SENSE_RETURN_ALL); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + + ExFreePool(modeData); + return(FALSE); + + } + } + +#if 0 + // + // Some drives incorrectly report this. In particular the SONY RMO-S350 + // when in disk mode. + // + + if (((PMODE_PARAMETER_HEADER) modeData)->MediumType >= MODE_FD_SINGLE_SIDE + && ((PMODE_PARAMETER_HEADER) modeData)->MediumType <= MODE_FD_MAXIMUM_TYPE) { + + DebugPrint((1, "ScsiFlop: MediumType value %2x, This is a floppy.\n", ((PMODE_PARAMETER_HEADER) modeData)->MediumType)); + ExFreePool(modeData); + return(TRUE); + } + +#endif + + // + // If the length is greater than length indiated by the mode data reset + // the data to the mode data. + // + if (length > (ULONG)((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) { + length = (ULONG)((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1; + + } + + // + // Look for the flexible disk mode page. + // + + pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE); + + if (pageData != NULL) { + + DebugPrint((1, "ScsiFlop: Flexible disk page found, This is a floppy.\n")); + + // + // As a special case for the floptical driver do a magic mode sense to + // enable the drive. + // + + ClassModeSense(DeviceObject, modeData, 0x2a, 0x2e); + + ExFreePool(modeData); + return(TRUE); + + } + + ExFreePool(modeData); + return(FALSE); + +} +#endif + + +NTSTATUS +DetermineMediaType( + PDEVICE_OBJECT DeviceObject + ) +/*++ + +Routine Description: + + This routine determines the floppy media type based on the size of the + device. The geometry information is set for the device object. + +Arguments: + + DeviceObject - Supplies the device object to be tested. + +Return Value: + + None + +--*/ +{ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; + PDISK_GEOMETRY geometry; + LONG index; + NTSTATUS status; + + PAGED_CODE(); + + geometry = &(fdoExtension->DiskGeometry); + + // + // Issue ReadCapacity to update device extension + // with information for current media. + // + + status = ClassReadDriveCapacity(DeviceObject); + + if (!NT_SUCCESS(status)) { + + // + // Set the media type to unknow and zero the geometry information. + // + + geometry->MediaType = Unknown; + + return status; + + } + + // + // Look at the capcity of disk to determine its type. + // + + for (index = NUMBER_OF_DRIVE_MEDIA_COMBINATIONS - 1; index >= 0; index--) { + + // + // Walk the table backward untill the drive capacity holds all of the + // data and the bytes per setor are equal + // + + if ((ULONG) (DriveMediaConstants[index].NumberOfHeads * + (DriveMediaConstants[index].MaximumTrack + 1) * + DriveMediaConstants[index].SectorsPerTrack * + DriveMediaConstants[index].BytesPerSector) <= + fdoExtension->CommonExtension.PartitionLength.LowPart && + DriveMediaConstants[index].BytesPerSector == + geometry->BytesPerSector) { + + geometry->MediaType = DriveMediaConstants[index].MediaType; + geometry->TracksPerCylinder = DriveMediaConstants[index].NumberOfHeads; + geometry->SectorsPerTrack = DriveMediaConstants[index].SectorsPerTrack; + geometry->Cylinders.LowPart = DriveMediaConstants[index].MaximumTrack+1; + break; + } + } + + if (index == -1) { + + // + // Set the media type to unknow and zero the geometry information. + // + + geometry->MediaType = Unknown; + + + } else { + // + // DMF check breaks the insight SCSI floppy, so its disabled for that case + // + PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; + + // if (diskData->EnableDMF == TRUE) { + + // + //check to see if DMF + // + + PSCSI_REQUEST_BLOCK srb; + PVOID readData; + + // + // Allocate a Srb for the read command. + // + +#ifndef __REACTOS__ + readData = ExAllocatePool(NonPagedPoolNx, geometry->BytesPerSector); +#else + readData = ExAllocatePool(NonPagedPool, geometry->BytesPerSector); +#endif + if (readData == NULL) { + return STATUS_NO_MEMORY; + } + +#ifndef __REACTOS__ + srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); +#else + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); +#endif + + if (srb == NULL) { + + ExFreePool(readData); + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(readData, geometry->BytesPerSector); + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + srb->CdbLength = 10; + srb->Cdb[0] = SCSIOP_READ; + srb->Cdb[5] = 0; + srb->Cdb[8] = (UCHAR) 1; + + // + // Set timeout value. + // + + srb->TimeOutValue = fdoExtension->TimeOutValue; + + // + // Send the mode select data. + // + + status = ClassSendSrbSynchronous(DeviceObject, + srb, + readData, + geometry->BytesPerSector, + FALSE + ); + + if (NT_SUCCESS(status)) { + char *pchar = (char *)readData; + + pchar += 3; //skip 3 bytes jump code + + // If the MSDMF3. signature is there then mark it as DMF diskette + if (RtlCompareMemory(pchar, "MSDMF3.", 7) == 7) { + diskData->IsDMF = TRUE; + } + + } + ExFreePool(readData); + ExFreePool(srb); + // }// else + } + return status; +} + +ULONG +DetermineDriveType( + PDEVICE_OBJECT DeviceObject + ) +/*++ + +Routine Description: + + The routine determines the device type so that the supported medias can be + determined. It does a mode sense for the default parameters. This code + assumes that the returned values are for the maximum device size. + +Arguments: + + DeviceObject - Supplies the device object to be tested. + +Return Value: + + None + +--*/ +{ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; + PVOID modeData; + PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; + PMODE_FLEXIBLE_DISK_PAGE pageData; + ULONG length; + LONG index; + UCHAR numberOfHeads; + UCHAR sectorsPerTrack; + USHORT maximumTrack; + BOOLEAN applyFix = FALSE; + + PAGED_CODE(); + + if (diskData->DriveType != DRIVE_TYPE_NONE) { + return(diskData->DriveType); + } + +#ifndef __REACTOS__ + modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); +#else + modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE); +#endif + + if (modeData == NULL) { + return(DRIVE_TYPE_NONE); + } + + RtlZeroMemory(modeData, MODE_DATA_SIZE); + + length = ClassModeSense(DeviceObject, + modeData, + MODE_DATA_SIZE, + MODE_PAGE_FLEXIBILE); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + + // + // Retry the request one more time + // in case of a check condition. + // + length = ClassModeSense(DeviceObject, + modeData, + MODE_DATA_SIZE, + MODE_PAGE_FLEXIBILE); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + + ExFreePool(modeData); + return(DRIVE_TYPE_NONE); + } + } + + // + // Look for the flexible disk mode page. + // + + pageData = ClassFindModePage( modeData, + length, + MODE_PAGE_FLEXIBILE, + TRUE); + + // + // Make sure the page is returned and is large enough. + // + + if ((pageData != NULL) && + (pageData->PageLength + 2 >= + (UCHAR)offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) { + + // + // Pull out the heads, cylinders, and sectors. + // + + numberOfHeads = pageData->NumberOfHeads; + maximumTrack = pageData->NumberOfCylinders[1]; + maximumTrack |= pageData->NumberOfCylinders[0] << 8; + sectorsPerTrack = pageData->SectorsPerTrack; + + + // + // Convert from number of cylinders to maximum track. + // + + maximumTrack--; + + // + // Search for the maximum supported media. Based on the number of heads, + // sectors per track and number of cylinders + // + for (index = 0; index < NUMBER_OF_DRIVE_MEDIA_COMBINATIONS; index++) { + + // + // Walk the table forward until the drive capacity holds all of the + // data and the bytes per setor are equal + // + + if (DriveMediaConstants[index].NumberOfHeads == numberOfHeads && + DriveMediaConstants[index].MaximumTrack == maximumTrack && + DriveMediaConstants[index].SectorsPerTrack ==sectorsPerTrack) { + + ExFreePool(modeData); + + // + // index is now a drive media combination. Compare this to + // the maximum drive media type in the drive media table. + // + + for (length = 0; length < NUMBER_OF_DRIVE_TYPES; length++) { + + if (DriveMediaLimits[length].HighestDriveMediaType == index) { + return(length); + } + } + return(DRIVE_TYPE_NONE); + } + } + + // If the maximum track is greater than 8 bits then divide the + // number of tracks by 3 and multiply the number of heads by 3. + // This is a special case for the 20.8 MB floppy. + // + + if (!applyFix && maximumTrack >= 0x0100) { + maximumTrack++; + maximumTrack /= 3; + maximumTrack--; + numberOfHeads *= 3; + } else { + ExFreePool(modeData); + return(DRIVE_TYPE_NONE); + } + + } + + ExFreePool(modeData); + return(DRIVE_TYPE_NONE); +} + + +BOOLEAN +FlCheckFormatParameters( + IN PDEVICE_OBJECT DeviceObject, + IN PFORMAT_PARAMETERS FormatParameters + ) + +/*++ + +Routine Description: + + This routine checks the supplied format parameters to make sure that + they'll work on the drive to be formatted. + +Arguments: + + DeviceObject - Pointer to the device object to be formated. + + FormatParameters - a pointer to the caller's parameters for the FORMAT. + +Return Value: + + TRUE if parameters are OK. + FALSE if the parameters are bad. + +--*/ + +{ + PDRIVE_MEDIA_CONSTANTS driveMediaConstants; + DRIVE_MEDIA_TYPE driveMediaType; + ULONG index; + + PAGED_CODE(); + + // + // Get the device type. + // + + index = DetermineDriveType(DeviceObject); + + if (index == DRIVE_TYPE_NONE) { + + // + // If the determine device type failed then just use the media type + // and try the parameters. + // + + driveMediaType = Drive360Media160; + + while (( DriveMediaConstants[driveMediaType].MediaType != + FormatParameters->MediaType ) && + ( driveMediaType < Drive288Media288) ) { + + driveMediaType++; + } + + } else { + + // + // Figure out which entry in the DriveMediaConstants table to use. + // + + driveMediaType = + DriveMediaLimits[index].HighestDriveMediaType; + + while ( ( DriveMediaConstants[driveMediaType].MediaType != + FormatParameters->MediaType ) && + ( driveMediaType > DriveMediaLimits[index]. + LowestDriveMediaType ) ) { + + driveMediaType--; + } + + } + + + // driveMediaType is bounded below by DriveMediaLimits[].LowestDriveMediaType +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:33010) // 33010: Enum used as array index may be negative +#endif + if ( DriveMediaConstants[driveMediaType].MediaType != + FormatParameters->MediaType ) { + return FALSE; + + } else { + + driveMediaConstants = &DriveMediaConstants[driveMediaType]; + + if ( ( FormatParameters->StartHeadNumber > + (ULONG)( driveMediaConstants->NumberOfHeads - 1 ) ) || + ( FormatParameters->EndHeadNumber > + (ULONG)( driveMediaConstants->NumberOfHeads - 1 ) ) || + ( FormatParameters->StartCylinderNumber > + driveMediaConstants->MaximumTrack ) || + ( FormatParameters->EndCylinderNumber > + driveMediaConstants->MaximumTrack ) || + ( FormatParameters->EndCylinderNumber < + FormatParameters->StartCylinderNumber ) ) { + + return FALSE; + + } else { + + return TRUE; + } + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +NTSTATUS +FormatMedia( + PDEVICE_OBJECT DeviceObject, + MEDIA_TYPE MediaType + ) +/*++ + +Routine Description: + + This routine formats the floppy disk. The entire floppy is formated in + one shot. + +Arguments: + + DeviceObject - Supplies the device object to be tested. + + Irp - Supplies a pointer to the requesting Irp. + + MediaType - Supplies the media type format the device for. + +Return Value: + + Returns a status for the operation. + +--*/ +{ + PVOID modeData; + PSCSI_REQUEST_BLOCK srb; + PMODE_FLEXIBLE_DISK_PAGE pageData; + DRIVE_MEDIA_TYPE driveMediaType; + PDRIVE_MEDIA_CONSTANTS driveMediaConstants; + ULONG length; + NTSTATUS status; + + PAGED_CODE(); + +#ifndef __REACTOS__ + modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); +#else + modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE); +#endif + + if (modeData == NULL) { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(modeData, MODE_DATA_SIZE); + + length = ClassModeSense(DeviceObject, + modeData, + MODE_DATA_SIZE, + MODE_PAGE_FLEXIBILE); + + if (length < sizeof(MODE_PARAMETER_HEADER)) { + ExFreePool(modeData); + return(STATUS_INVALID_DEVICE_REQUEST); + } + + // + // Look for the flexible disk mode page. + // + + pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE); + + // + // Make sure the page is returned and is large enough. + // + + if ((pageData == NULL) || + (pageData->PageLength + 2 < + (UCHAR)offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) { + + ExFreePool(modeData); + return(STATUS_INVALID_DEVICE_REQUEST); + + } + + // + // Look for a drive media type which matches the requested media type. + // + // + //start from Drive120MMedia120M instead of Drive2080Media2080 + // + for (driveMediaType = Drive120MMedia120M; + DriveMediaConstants[driveMediaType].MediaType != MediaType; + driveMediaType--) { + if (driveMediaType == Drive360Media160) { + + ExFreePool(modeData); + return(STATUS_INVALID_PARAMETER); + + } + } + + driveMediaConstants = &DriveMediaConstants[driveMediaType]; + + if ((pageData->NumberOfHeads != driveMediaConstants->NumberOfHeads) || + (pageData->SectorsPerTrack != driveMediaConstants->SectorsPerTrack) || + ((pageData->NumberOfCylinders[0] != (UCHAR)((driveMediaConstants->MaximumTrack+1) >> 8)) && + (pageData->NumberOfCylinders[1] != (UCHAR)driveMediaConstants->MaximumTrack+1)) || + (pageData->BytesPerSector[0] != driveMediaConstants->BytesPerSector >> 8 )) { + + // + // Update the flexible parameters page with the new parameters. + // + + pageData->NumberOfHeads = driveMediaConstants->NumberOfHeads; + pageData->SectorsPerTrack = driveMediaConstants->SectorsPerTrack; + pageData->NumberOfCylinders[0] = (UCHAR)((driveMediaConstants->MaximumTrack+1) >> 8); + pageData->NumberOfCylinders[1] = (UCHAR)driveMediaConstants->MaximumTrack+1; + pageData->BytesPerSector[0] = driveMediaConstants->BytesPerSector >> 8; + + // + // Clear the mode parameter header. + // + + RtlZeroMemory(modeData, sizeof(MODE_PARAMETER_HEADER)); + + // + // Set the length equal to the length returned for the flexible page. + // + + length = pageData->PageLength + 2; + + // + // Copy the page after the mode parameter header. + // + + RtlMoveMemory((PCHAR) modeData + sizeof(MODE_PARAMETER_HEADER), + pageData, + length + ); + length += sizeof(MODE_PARAMETER_HEADER); + + + // + // Allocate a Srb for the format command. + // + +#ifndef __REACTOS__ + srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); +#else + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); +#endif + + if (srb == NULL) { + + ExFreePool(modeData); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + srb->CdbLength = 6; + srb->Cdb[0] = SCSIOP_MODE_SELECT; + srb->Cdb[4] = (UCHAR) length; + + // + // Set the PF bit. + // + + srb->Cdb[1] |= 0x10; + + // + // Set timeout value. + // + + srb->TimeOutValue = 2; + + // + // Send the mode select data. + // + + status = ClassSendSrbSynchronous(DeviceObject, + srb, + modeData, + length, + TRUE + ); + + // + // The mode data not needed any more so free it. + // + + ExFreePool(modeData); + + if (!NT_SUCCESS(status)) { + ExFreePool(srb); + return(status); + } + + } else { + + // + // The mode data not needed any more so free it. + // + + ExFreePool(modeData); + + // + // Allocate a Srb for the format command. + // + +#ifndef __REACTOS__ + srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); +#else + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); +#endif + + if (srb == NULL) { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + } + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + srb->CdbLength = 6; + + srb->Cdb[0] = SCSIOP_FORMAT_UNIT; + + // + // Set timeout value. + // + + srb->TimeOutValue = 10 * 60; + + status = ClassSendSrbSynchronous(DeviceObject, + srb, + NULL, + 0, + FALSE + ); + ExFreePool(srb); + + return(status); + +} + +VOID +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopProcessError( + PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + NTSTATUS *Status, + BOOLEAN *Retry + ) +/*++ + +Routine Description: + + This routine checks the type of error. If the error indicate the floppy + controller needs to be reinitialize a command is made to do it. + +Arguments: + + DeviceObject - Supplies a pointer to the device object. + + Srb - Supplies a pointer to the failing Srb. + + Status - Status with which the IRP will be completed. + + Retry - Indication of whether the request will be retried. + +Return Value: + + None. + +--*/ + +{ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; + PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; + PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; + PIO_STACK_LOCATION irpStack; + PIRP irp; + PSCSI_REQUEST_BLOCK srb; + LARGE_INTEGER largeInt; + PCOMPLETION_CONTEXT context; + PCDB cdb; + ULONG_PTR alignment; + ULONG majorFunction; + + UNREFERENCED_PARAMETER(Status); + UNREFERENCED_PARAMETER(Retry); + + largeInt.QuadPart = 1; + + // + // Check the status. The initialization command only needs to be sent + // if UNIT ATTENTION or LUN NOT READY is returned. + // + + if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { + + // + // The drive does not require reinitialization. + // + + return; + } + + // + // Reset the drive type. + // + + diskData->DriveType = DRIVE_TYPE_NONE; + diskData->IsDMF = FALSE; + + fdoExtension->DiskGeometry.MediaType = Unknown; + + if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) { + + // FLPYDISK.SYS never returns a non-zero value for the ChangeCount + // on an IOCTL_DISK_CHECK_VERIFY. Some things seem to work better + // if we do the same. In particular, FatVerifyVolume() can exit between + // the IOCTL_DISK_CHECK_VERIFY and the IOCTL_DISK_GET_DRIVE_GEOMETRY + // if a non-zero ChangeCount is returned, and this appears to cause + // issues formatting unformatted media in some situations. + // + // This is something that should probably be revisited at some point. + // + fdoExtension->MediaChangeCount = 0; + + if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) && + (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_MEDIUM_CHANGED)) { + + struct _START_STOP *startStopCdb; + + DebugPrint((2,"Sending SCSIOP_START_STOP_UNIT\n")); + +#ifndef __REACTOS__ + context = ExAllocatePool(NonPagedPoolNx, +#else + context = ExAllocatePool(NonPagedPool, +#endif + sizeof(COMPLETION_CONTEXT)); + + if (context == NULL) { + + return; + } +#if (NTDDI_VERSION >= NTDDI_WIN8) + srb = &context->Srb.Srb; +#else + srb = &context->Srb; +#endif + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + srb->SrbFlags = SRB_FLAGS_DISABLE_AUTOSENSE; + + srb->CdbLength = 6; + + startStopCdb = (struct _START_STOP *)srb->Cdb; + + startStopCdb->OperationCode = SCSIOP_START_STOP_UNIT; + startStopCdb->Start = 1; + + // A Start Stop Unit request has no transfer buffer. + // Set the request to IRP_MJ_FLUSH_BUFFERS when calling + // IoBuildAsynchronousFsdRequest() so that it ignores + // the buffer pointer and buffer length parameters. + // + majorFunction = IRP_MJ_FLUSH_BUFFERS; + + } else if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_MEDIUM_ERROR) { + + // Return ERROR_UNRECOGNIZED_MEDIA instead of + // STATUS_DEVICE_DATA_ERROR to make shell happy. + // + *Status = STATUS_UNRECOGNIZED_MEDIA; + return; + + } else { + + return; + } + +#ifndef __REACTOS__ + } else if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_NOT_READY) && + senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_INIT_COMMAND_REQUIRED || + (senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { +#else + } else if ((((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_NOT_READY) && + senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_INIT_COMMAND_REQUIRED) || + (senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { +#endif + + ULONG sizeNeeded; + ULONG tmpSize; + BOOLEAN overFlow; + + DebugPrint((1, "ScsiFlopProcessError: Reinitializing the floppy.\n")); + + // + // Send the special mode sense command to enable writes on the + // floptical drive. + // + + alignment = DeviceObject->AlignmentRequirement ? + DeviceObject->AlignmentRequirement : 1; + + sizeNeeded = 0; + overFlow = TRUE; + if (SUCCEEDED(ULongAdd(sizeof(COMPLETION_CONTEXT), 0x2a, &tmpSize))) { + + if (SUCCEEDED(ULongAdd(tmpSize, (ULONG) alignment, &sizeNeeded))) { + overFlow = FALSE; + } + } + + context = NULL; + + if (!overFlow) { +#ifndef __REACTOS__ + context = ExAllocatePool(NonPagedPoolNx, sizeNeeded); +#else + context = ExAllocatePool(NonPagedPool, sizeNeeded); +#endif + } + + if (context == NULL) { + + // + // If there is not enough memory to fulfill this request, + // simply return. A subsequent retry will fail and another + // chance to start the unit. + // + + return; + } + +#if (NTDDI_VERSION >= NTDDI_WIN8) + srb = &context->Srb.Srb; +#else + srb = &context->Srb; +#endif + + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + // + // Set the transfer length. + // + + srb->DataTransferLength = 0x2a; + srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + // + // The data buffer must be aligned. + // + + srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) & + ~(alignment - 1)); + + + // + // Build the start unit CDB. + // + + srb->CdbLength = 6; + cdb = (PCDB)srb->Cdb; + cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; + cdb->MODE_SENSE.PageCode = 0x2e; + cdb->MODE_SENSE.AllocationLength = 0x2a; + + majorFunction = IRP_MJ_READ; + + } else { + + return; + } + + context->DeviceObject = DeviceObject; + + // + // Write length to SRB. + // + + srb->Length = SCSI_REQUEST_BLOCK_SIZE; + + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + srb->TimeOutValue = fdoExtension->TimeOutValue; + + // + // Build the asynchronous request + // to be sent to the port driver. + // + + irp = IoBuildAsynchronousFsdRequest(majorFunction, + DeviceObject, + srb->DataBuffer, + srb->DataTransferLength, + &largeInt, + NULL); + + if(irp == NULL) { + ExFreePool(context); + return; + } + + + IoSetCompletionRoutine(irp, + (PIO_COMPLETION_ROUTINE)ClassAsynchronousCompletion, + context, + TRUE, + TRUE, + TRUE); + + ClassAcquireRemoveLock(DeviceObject, irp); + + irpStack = IoGetNextIrpStackLocation(irp); + + irpStack->MajorFunction = IRP_MJ_SCSI; + + srb->OriginalRequest = irp; + + // + // Save SRB address in next stack for port driver. + // + + irpStack->Parameters.Others.Argument1 = (PVOID)srb; + + // + // Can't release the remove lock yet - let ClassAsynchronousCompletion + // take care of that for us. + // + + (VOID)IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp); + + return; +} + +NTSTATUS +FlopticalFormatMedia( + PDEVICE_OBJECT DeviceObject, + PFORMAT_PARAMETERS Format + ) +/*++ + +Routine Description: + + This routine is used to do perform a format tracks for the 20.8 MB + floppy. Because the device does not support format tracks and the full + format takes a long time a write of zeros is done instead. + +Arguments: + + DeviceObject - Supplies the device object to be tested. + + Format - Supplies the format parameters. + +Return Value: + + Returns a status for the operation. + +--*/ +{ + IO_STATUS_BLOCK ioStatus; + PIRP irp; + KEVENT event; + LARGE_INTEGER offset; + ULONG length; + PVOID buffer; + PDRIVE_MEDIA_CONSTANTS driveMediaConstants; + NTSTATUS status; + + PAGED_CODE(); + + driveMediaConstants = &DriveMediaConstants[Drive2080Media2080]; + + // + // Calculate the length of the buffer. + // + + length = ((Format->EndCylinderNumber - Format->StartCylinderNumber) * + driveMediaConstants->NumberOfHeads + + Format->EndHeadNumber - Format->StartHeadNumber + 1) * + driveMediaConstants->SectorsPerTrack * + driveMediaConstants->BytesPerSector; + +#ifndef __REACTOS__ + buffer = ExAllocatePool(NonPagedPoolNxCacheAligned, length); +#else + buffer = ExAllocatePool(NonPagedPoolCacheAligned, length); +#endif + + if (buffer == NULL) { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(buffer, length); + + offset.QuadPart = + (Format->StartCylinderNumber * driveMediaConstants->NumberOfHeads + + Format->StartHeadNumber) * driveMediaConstants->SectorsPerTrack * + driveMediaConstants->BytesPerSector; + + // + // Set the event object to the unsignaled state. + // It will be used to signal request completion. + // + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Build the synchronous request with data transfer. + // + + irp = IoBuildSynchronousFsdRequest( + IRP_MJ_WRITE, + DeviceObject, + buffer, + length, + &offset, + &event, + &ioStatus); + + if (irp != NULL) { + status = IoCallDriver(DeviceObject, irp); + + if (status == STATUS_PENDING) { + + // + // Wait for the request to complete if necessary. + // + + KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); + } + + // + // If the call driver suceeded then set the status to the status block. + // + + if (NT_SUCCESS(status)) { + status = ioStatus.Status; + } + } else { + status = STATUS_INSUFFICIENT_RESOURCES; + } + + ExFreePool(buffer); + + return(status); + +} + + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopRemoveDevice( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR Type + ) +/*++ + +Routine Description: + + This routine is responsible for releasing any resources in use by the + sfloppy driver. This routine is called + when all outstanding requests have been completed and the driver has + disappeared - no requests may be issued to the lower drivers. + +Arguments: + + DeviceObject - the device object being removed + + Type - the type of remove operation (QUERY, REMOVE or CANCEL) + +Return Value: + + for a query - success if the device can be removed or a failure code + indiciating why not. + + for a remove or cancel - STATUS_SUCCESS + +--*/ + +{ + PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = + DeviceObject->DeviceExtension; + PDISK_DATA diskData = deviceExtension->CommonExtension.DriverData; + NTSTATUS status; + + PAGED_CODE(); + + if((Type == IRP_MN_QUERY_REMOVE_DEVICE) || + (Type == IRP_MN_CANCEL_REMOVE_DEVICE)) { + return STATUS_SUCCESS; + } + + if (Type == IRP_MN_REMOVE_DEVICE){ + if(deviceExtension->DeviceDescriptor) { + ExFreePool(deviceExtension->DeviceDescriptor); + deviceExtension->DeviceDescriptor = NULL; + } + + if(deviceExtension->AdapterDescriptor) { + ExFreePool(deviceExtension->AdapterDescriptor); + deviceExtension->AdapterDescriptor = NULL; + } + + if(deviceExtension->SenseData) { + ExFreePool(deviceExtension->SenseData); + deviceExtension->SenseData = NULL; + } + + ClassDeleteSrbLookasideList(&deviceExtension->CommonExtension); + } + + if(diskData->FloppyInterfaceString.Buffer != NULL) { + + status = IoSetDeviceInterfaceState( + &(diskData->FloppyInterfaceString), + FALSE); + + if (!NT_SUCCESS(status)) { + // Failed to disable device interface during removal. Not a fatal error. + DebugPrint((1, "ScsiFlopRemoveDevice: Unable to set device " + "interface state to FALSE for fdo %p " + "[%08lx]\n", + DeviceObject, status)); + } + + RtlFreeUnicodeString(&(diskData->FloppyInterfaceString)); + RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL); + } + + if(Type == IRP_MN_REMOVE_DEVICE) { + IoGetConfigurationInformation()->FloppyCount--; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +#ifdef __REACTOS__ +NTAPI +#endif +ScsiFlopStopDevice( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR Type + ) +{ + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Type); + + return STATUS_SUCCESS; +} + + +NTSTATUS +USBFlopGetMediaTypes( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) +{ +/*++ + +Routine Description: + + This routines determines the current or default geometry of the drive + for IOCTL_DISK_GET_DRIVE_GEOMETRY, or all currently supported geometries + of the drive (which is determined by its currently inserted media) for + IOCTL_DISK_GET_MEDIA_TYPES. + + The returned geometries are determined by issuing a Read Format Capacities + request and then matching the returned {Number of Blocks, Block Length} + pairs in a table of known floppy geometries. + +Arguments: + + DeviceObject - Supplies the device object. + + Irp - A IOCTL_DISK_GET_DRIVE_GEOMETRY or a IOCTL_DISK_GET_MEDIA_TYPES Irp. + If NULL, the device geometry is updated with the current device + geometry. + +Return Value: + + Status is returned. + +--*/ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; + PIO_STACK_LOCATION irpStack; + ULONG ioControlCode; + PDISK_GEOMETRY outputBuffer; + PDISK_GEOMETRY outputBufferEnd; + ULONG outputBufferLength; + PSCSI_REQUEST_BLOCK srb; + PVOID dataBuffer; + ULONG dataTransferLength; + struct _READ_FORMATTED_CAPACITIES *cdb; + PFORMATTED_CAPACITY_LIST capList; + NTSTATUS status; + + PAGED_CODE(); + + fdoExtension = DeviceObject->DeviceExtension; + + if (Irp != NULL) { + + // Get the Irp parameters + // + irpStack = IoGetCurrentIrpStackLocation(Irp); + + ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; + + Irp->IoStatus.Information = 0; + + outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; + + outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; + + if (outputBufferLength < sizeof(DISK_GEOMETRY)) + { + return STATUS_BUFFER_TOO_SMALL; + } + + // Pointer arithmetic to allow multiple DISK_GEOMETRY's to be returned. + // Rounds BufferEnd down to integral multiple of DISK_GEOMETRY structs. + // + outputBufferEnd = outputBuffer + + outputBufferLength / sizeof(DISK_GEOMETRY); + + } else { + + // No Irp to return the result in, just update the current geometry + // in the device extension. + // + ioControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY; + + outputBuffer = NULL; + + outputBufferEnd = NULL; + + outputBufferLength = 0; + } + + if (ioControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) { + + fdoExtension->DiskGeometry.MediaType = Unknown; + + status = ClassReadDriveCapacity(DeviceObject); + + if (!NT_SUCCESS(status)) + { + // If the media is not recongized, we want to return the default + // geometry so that the media can be formatted. Unrecognized media + // causes SCSI_SENSE_MEDIUM_ERROR, which gets reported as + // STATUS_DEVICE_DATA_ERROR. Ignore these errors, but return other + // errors, such as STATUS_NO_MEDIA_IN_DEVICE. + // + if (status != STATUS_UNRECOGNIZED_MEDIA) + { + DebugPrint((2,"IOCTL_DISK_GET_DRIVE_GEOMETRY returns %08X\n", status)); + + return status; + } + } + } + + // Allocate an SRB for the SCSIOP_READ_FORMATTED_CAPACITY request + // +#ifndef __REACTOS__ + srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); +#else + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); +#endif + + if (srb == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Allocate a transfer buffer for the SCSIOP_READ_FORMATTED_CAPACITY request + // The length of the returned descriptor array is limited to a byte field + // in the capacity list header. + // + dataTransferLength = sizeof(FORMATTED_CAPACITY_LIST) + + 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR); + + ASSERT(dataTransferLength < 0x100); + +#ifndef __REACTOS__ + dataBuffer = ExAllocatePool(NonPagedPoolNx, dataTransferLength); +#else + dataBuffer = ExAllocatePool(NonPagedPool, dataTransferLength); +#endif + + if (dataBuffer == NULL) + { + ExFreePool(srb); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Initialize the SRB and CDB + // + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + RtlZeroMemory(dataBuffer, dataTransferLength); + + srb->CdbLength = sizeof(struct _READ_FORMATTED_CAPACITIES); + + srb->TimeOutValue = fdoExtension->TimeOutValue; + + cdb = (struct _READ_FORMATTED_CAPACITIES *)srb->Cdb; + + cdb->OperationCode = SCSIOP_READ_FORMATTED_CAPACITY; + cdb->AllocationLength[1] = (UCHAR)dataTransferLength; + + // + // Send down the SCSIOP_READ_FORMATTED_CAPACITY request + // + status = ClassSendSrbSynchronous(DeviceObject, + srb, + dataBuffer, + dataTransferLength, + FALSE); + + capList = (PFORMATTED_CAPACITY_LIST)dataBuffer; + + // If we don't get as much data as requested, it is not an error. + // + if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) + { + status = STATUS_SUCCESS; + } + + if (NT_SUCCESS(status) && + srb->DataTransferLength >= sizeof(FORMATTED_CAPACITY_LIST) && + capList->CapacityListLength && + capList->CapacityListLength % sizeof(FORMATTED_CAPACITY_DESCRIPTOR) == 0) + { + ULONG NumberOfBlocks; + ULONG BlockLength; + ULONG count; + ULONG i, j; + LONG currentGeometry; + BOOLEAN capacityMatches[FLOPPY_CAPACITIES]; + + // Subtract the size of the Capacity List Header to get + // just the size of the Capacity List Descriptor array. + // + srb->DataTransferLength -= sizeof(FORMATTED_CAPACITY_LIST); + + // Only look at the Capacity List Descriptors that were actually + // returned. + // + if (srb->DataTransferLength < capList->CapacityListLength) + { + count = srb->DataTransferLength / + sizeof(FORMATTED_CAPACITY_DESCRIPTOR); + } + else + { + count = capList->CapacityListLength / + sizeof(FORMATTED_CAPACITY_DESCRIPTOR); + } + + // Updated only if a match is found for the first Capacity List + // Descriptor returned by the device. + // + currentGeometry = -1; + + // Initialize the array of capacities that hit a match. + // + RtlZeroMemory(capacityMatches, sizeof(capacityMatches)); + + // Iterate over each Capacity List Descriptor returned from the device + // and record matching capacities in the capacity match array. + // + for (i = 0; i < count; i++) + { + NumberOfBlocks = (capList->Descriptors[i].NumberOfBlocks[0] << 24) + + (capList->Descriptors[i].NumberOfBlocks[1] << 16) + + (capList->Descriptors[i].NumberOfBlocks[2] << 8) + + (capList->Descriptors[i].NumberOfBlocks[3]); + + BlockLength = (capList->Descriptors[i].BlockLength[0] << 16) + + (capList->Descriptors[i].BlockLength[1] << 8) + + (capList->Descriptors[i].BlockLength[2]); + + // Given the {NumberOfBlocks, BlockLength} from this Capacity List + // Descriptor, find a matching entry in FloppyCapacities[]. + // + for (j = 0; j < FLOPPY_CAPACITIES; j++) + { + if (NumberOfBlocks == FloppyCapacities[j].NumberOfBlocks && + BlockLength == FloppyCapacities[j].BlockLength) + { + // A matching capacity was found, record it. + // + capacityMatches[j] = TRUE; + + // A match was found for the first Capacity List + // Descriptor returned by the device. + // + if (i == 0) + { + currentGeometry = j; + } + } else if ((capList->Descriptors[i].Valid) && + (BlockLength == FloppyCapacities[j].BlockLength)) { + + ULONG inx; + ULONG mediaInx; + + // + // Check if this is 32MB media type. 32MB media + // reports variable NumberOfBlocks. So we cannot + // use that to determine the drive type + // + inx = DetermineDriveType(DeviceObject); + if (inx != DRIVE_TYPE_NONE) { + mediaInx = DriveMediaLimits[inx].HighestDriveMediaType; + if ((DriveMediaConstants[mediaInx].MediaType) + == F3_32M_512) { + capacityMatches[j] = TRUE; + + if (i == 0) { + currentGeometry = j; + } + } + } + } + } + } + + // Default status is STATUS_UNRECOGNIZED_MEDIA, unless we return + // either STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW. + // + status = STATUS_UNRECOGNIZED_MEDIA; + + if (ioControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) { + + if (currentGeometry != -1) + { + // Update the current device geometry + // + fdoExtension->DiskGeometry = FloppyGeometries[currentGeometry]; + + // + // Calculate sector to byte shift. + // + + WHICH_BIT(fdoExtension->DiskGeometry.BytesPerSector, + fdoExtension->SectorShift); + + fdoExtension->CommonExtension.PartitionLength.QuadPart = + (LONGLONG)FloppyCapacities[currentGeometry].NumberOfBlocks * + FloppyCapacities[currentGeometry].BlockLength; + + DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n", + fdoExtension->DiskGeometry.Cylinders.LowPart, + fdoExtension->DiskGeometry.MediaType, + fdoExtension->DiskGeometry.TracksPerCylinder, + fdoExtension->DiskGeometry.SectorsPerTrack, + fdoExtension->DiskGeometry.BytesPerSector, + fdoExtension->SectorShift, + fdoExtension->CommonExtension.PartitionLength.LowPart)); + + // Return the current device geometry + // + if (Irp != NULL) + { + *outputBuffer = FloppyGeometries[currentGeometry]; + + Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); + } + + status = STATUS_SUCCESS; + } + + } else { + + // Iterate over the capacities and return the geometry + // corresponding to each matching Capacity List Descriptor + // returned from the device. + // + // The resulting list should be in sorted ascending order, + // assuming that the FloppyGeometries[] array is in sorted + // ascending order. + // + for (i = 0; i < FLOPPY_CAPACITIES; i++) + { + if (capacityMatches[i] && FloppyCapacities[i].CanFormat) + { + if (outputBuffer < outputBufferEnd) + { + *outputBuffer++ = FloppyGeometries[i]; + + Irp->IoStatus.Information += sizeof(DISK_GEOMETRY); + + DebugPrint((2,"geometry : %3d %2d %d %2d %4d\n", + FloppyGeometries[i].Cylinders.LowPart, + FloppyGeometries[i].MediaType, + FloppyGeometries[i].TracksPerCylinder, + FloppyGeometries[i].SectorsPerTrack, + FloppyGeometries[i].BytesPerSector)); + + status = STATUS_SUCCESS; + } + else + { + // We ran out of output buffer room before we ran out + // geometries to return. + // + status = STATUS_BUFFER_OVERFLOW; + } + } + } + } + } + else if (NT_SUCCESS(status)) + { + // The SCSIOP_READ_FORMATTED_CAPACITY request was successful, but + // returned data does not appear valid. + // + status = STATUS_UNSUCCESSFUL; + } + + ExFreePool(dataBuffer); + ExFreePool(srb); + + return status; +} + + +NTSTATUS +USBFlopFormatTracks( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) +{ +/*++ + +Routine Description: + + This routines formats the specified tracks. If multiple tracks are + specified, each is formatted with a separate Format Unit request. + +Arguments: + + DeviceObject - Supplies the device object. + + Irp - A IOCTL_DISK_FORMAT_TRACKS Irp. + +Return Value: + + Status is returned. + +--*/ + PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; + PIO_STACK_LOCATION irpStack; + PFORMAT_PARAMETERS formatParameters; + PDISK_GEOMETRY geometry; + PFORMATTED_CAPACITY capacity; + PSCSI_REQUEST_BLOCK srb; + PFORMAT_UNIT_PARAMETER_LIST parameterList; + PCDB12FORMAT cdb; + ULONG i; + ULONG cylinder, head; + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + fdoExtension = DeviceObject->DeviceExtension; + + // Get the Irp parameters + // + irpStack = IoGetCurrentIrpStackLocation(Irp); + + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < + sizeof(FORMAT_PARAMETERS)) + { + return STATUS_INVALID_PARAMETER; + } + + formatParameters = (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; + + // Find the geometry / capacity entries corresponding to the format + // parameters MediaType + // + geometry = NULL; + capacity = NULL; + + for (i=0; i<FLOPPY_CAPACITIES; i++) + { + if (FloppyGeometries[i].MediaType == formatParameters->MediaType) + { + geometry = &FloppyGeometries[i]; + capacity = &FloppyCapacities[i]; + + break; + } + } + + if (geometry == NULL) + { + return STATUS_INVALID_PARAMETER; + } + + // Check if the format parameters are valid + // + if ((formatParameters->StartCylinderNumber > + geometry->Cylinders.LowPart - 1) || + + (formatParameters->EndCylinderNumber > + geometry->Cylinders.LowPart - 1) || + + (formatParameters->StartHeadNumber > + geometry->TracksPerCylinder - 1) || + + (formatParameters->EndHeadNumber > + geometry->TracksPerCylinder - 1) || + + (formatParameters->StartCylinderNumber > + formatParameters->EndCylinderNumber) || + + (formatParameters->StartHeadNumber > + formatParameters->EndHeadNumber)) + { + return STATUS_INVALID_PARAMETER; + } + + // Don't low level format LS-120 media, Imation says it's best to not + // do this. + // + if ((formatParameters->MediaType == F3_120M_512) || + (formatParameters->MediaType == F3_240M_512) || + (formatParameters->MediaType == F3_32M_512)) + { + return STATUS_SUCCESS; + } + + // Allocate an SRB for the SCSIOP_FORMAT_UNIT request + // +#ifndef __REACTOS__ + srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); +#else + srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); +#endif + + if (srb == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Allocate a transfer buffer for the SCSIOP_FORMAT_UNIT parameter list + // +#ifndef __REACTOS__ + parameterList = ExAllocatePool(NonPagedPoolNx, +#else + parameterList = ExAllocatePool(NonPagedPool, +#endif + sizeof(FORMAT_UNIT_PARAMETER_LIST)); + + if (parameterList == NULL) + { + ExFreePool(srb); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Initialize the parameter list + // + RtlZeroMemory(parameterList, sizeof(FORMAT_UNIT_PARAMETER_LIST)); + + parameterList->DefectListHeader.SingleTrack = 1; + parameterList->DefectListHeader.DisableCert = 1; // TEAC requires this set + parameterList->DefectListHeader.FormatOptionsValid = 1; + parameterList->DefectListHeader.DefectListLengthLsb = 8; + + parameterList->FormatDescriptor.NumberOfBlocks[0] = + (UCHAR)((capacity->NumberOfBlocks >> 24) & 0xFF); + + parameterList->FormatDescriptor.NumberOfBlocks[1] = + (UCHAR)((capacity->NumberOfBlocks >> 16) & 0xFF); + + parameterList->FormatDescriptor.NumberOfBlocks[2] = + (UCHAR)((capacity->NumberOfBlocks >> 8) & 0xFF); + + parameterList->FormatDescriptor.NumberOfBlocks[3] = + (UCHAR)(capacity->NumberOfBlocks & 0xFF); + + parameterList->FormatDescriptor.BlockLength[0] = + (UCHAR)((capacity->BlockLength >> 16) & 0xFF); + + parameterList->FormatDescriptor.BlockLength[1] = + (UCHAR)((capacity->BlockLength >> 8) & 0xFF); + + parameterList->FormatDescriptor.BlockLength[2] = + (UCHAR)(capacity->BlockLength & 0xFF); + + + for (cylinder = formatParameters->StartCylinderNumber; + cylinder <= formatParameters->EndCylinderNumber; + cylinder++) + { + for (head = formatParameters->StartHeadNumber; + head <= formatParameters->EndHeadNumber; + head++) + { + // Initialize the SRB and CDB + // + RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); + + srb->CdbLength = sizeof(CDB12FORMAT); + + srb->TimeOutValue = fdoExtension->TimeOutValue; + + cdb = (PCDB12FORMAT)srb->Cdb; + + cdb->OperationCode = SCSIOP_FORMAT_UNIT; + cdb->DefectListFormat = 7; + cdb->FmtData = 1; + cdb->TrackNumber = (UCHAR)cylinder; + cdb->ParameterListLengthLsb = sizeof(FORMAT_UNIT_PARAMETER_LIST); + + parameterList->DefectListHeader.Side = (UCHAR)head; + + // + // Send down the SCSIOP_FORMAT_UNIT request + // + status = ClassSendSrbSynchronous(DeviceObject, + srb, + parameterList, + sizeof(FORMAT_UNIT_PARAMETER_LIST), + TRUE); + + if (!NT_SUCCESS(status)) + { + break; + } + } + if (!NT_SUCCESS(status)) + { + break; + } + } + + if (NT_SUCCESS(status) && formatParameters->StartCylinderNumber == 0) + { + // Update the device geometry + // + + DebugPrint((2,"geometry was: %3d %2d %d %2d %4d %2d %08X\n", + fdoExtension->DiskGeometry.Cylinders.LowPart, + fdoExtension->DiskGeometry.MediaType, + fdoExtension->DiskGeometry.TracksPerCylinder, + fdoExtension->DiskGeometry.SectorsPerTrack, + fdoExtension->DiskGeometry.BytesPerSector, + fdoExtension->SectorShift, + fdoExtension->CommonExtension.PartitionLength.LowPart)); + + fdoExtension->DiskGeometry = *geometry; + + // + // Calculate sector to byte shift. + // + + WHICH_BIT(fdoExtension->DiskGeometry.BytesPerSector, + fdoExtension->SectorShift); + + fdoExtension->CommonExtension.PartitionLength.QuadPart = + (LONGLONG)capacity->NumberOfBlocks * + capacity->BlockLength; + + DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n", + fdoExtension->DiskGeometry.Cylinders.LowPart, + fdoExtension->DiskGeometry.MediaType, + fdoExtension->DiskGeometry.TracksPerCylinder, + fdoExtension->DiskGeometry.SectorsPerTrack, + fdoExtension->DiskGeometry.BytesPerSector, + fdoExtension->SectorShift, + fdoExtension->CommonExtension.PartitionLength.LowPart)); + } + + // Free everything we allocated + // + ExFreePool(parameterList); + ExFreePool(srb); + + return status; +} + diff --git a/drivers/storage/floppy_new/floppy.rc b/drivers/storage/floppy_new/floppy.rc new file mode 100644 index 0000000000..d23ec119d4 --- /dev/null +++ b/drivers/storage/floppy_new/floppy.rc @@ -0,0 +1,13 @@ +/* + * PROJECT: ReactOS Floppy Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/storage/floppy/floppy.rc + * PURPOSE: Resource definition file + * PROGRAMMERS: Vizzini (vizzini(a)plasmic.com) + */ + +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "Floppy Disk Controller Driver" +#define REACTOS_STR_INTERNAL_NAME "floppy" +#define REACTOS_STR_ORIGINAL_FILENAME "floppy.sys" +#include <reactos/version.rc> diff --git a/drivers/storage/floppy_new/floppy_reg.inf b/drivers/storage/floppy_new/floppy_reg.inf new file mode 100644 index 0000000000..ad620f4b3e --- /dev/null +++ b/drivers/storage/floppy_new/floppy_reg.inf @@ -0,0 +1,7 @@ +; Floppy driver +[AddReg] +HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","ErrorControl",0x00010001,0x00000000 +HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","Group",0x00000000,"Primary Disk" +HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","ImagePath",0x00020000,"system32\drivers\floppy.sys" +HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","Start",0x00010001,0x00000001 +HKLM,"SYSTEM\CurrentControlSet\Services\Floppy","Type",0x00010001,0x00000001 diff --git a/drivers/storage/floppy_new/guid.c b/drivers/storage/floppy_new/guid.c new file mode 100644 index 0000000000..757901b422 --- /dev/null +++ b/drivers/storage/floppy_new/guid.c @@ -0,0 +1,11 @@ +/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ + +#include <ntdef.h> +#include <initguid.h> +#include <ioevent.h> +#include <wdmguid.h> + +#define DEVICE_TYPE ULONG +#include <ntddstor.h> + +/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/media/doc/README.FSD b/media/doc/README.FSD index 8d9993d40f..4f28521245 100644 --- a/media/doc/README.FSD +++ b/media/doc/README.FSD @@ -19,7 +19,8 @@ reactos/drivers/filesystems/reiserfs # Synced to 0.26 The following FSD are shared with:
https://github.com/Microsoft/Windows-driver-samples
reactos/drivers/filesystems/fastfat_new # Synced to 2817004 -reactos/drivers/filesystems/cdfs_new # Synced to f73e552 +reactos/drivers/filesystems/cdfs # Synced to f73e552 +reactos/drivers/storage/floppy_new # Synced to 9d23d43 The following FS libs are shared with:
https://github.com/dosfstools/dosfstools
reactos/sdk/lib/fslib/vfatlib/check # Synced to 4.1
5 years, 10 months
1
0
0
0
[reactos] 01/02: [PSDK] Complete the MEDIA_TYPE enum
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3ceb93a4f2663a339d810…
commit 3ceb93a4f2663a339d81037df66d69dd1cd31a3d Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Sat Dec 15 19:18:35 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Sat Dec 15 20:04:00 2018 +0100 [PSDK] Complete the MEDIA_TYPE enum --- sdk/include/psdk/ntdddisk.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdk/include/psdk/ntdddisk.h b/sdk/include/psdk/ntdddisk.h index 9deb6abc79..24387a02d5 100644 --- a/sdk/include/psdk/ntdddisk.h +++ b/sdk/include/psdk/ntdddisk.h @@ -321,7 +321,10 @@ typedef enum _MEDIA_TYPE { F5_1Pt23_1024, F3_128Mb_512, F3_230Mb_512, - F8_256_128 + F8_256_128, + F3_200Mb_512, + F3_240M_512, + F3_32M_512 } MEDIA_TYPE, *PMEDIA_TYPE; typedef enum _DETECTION_TYPE {
5 years, 10 months
1
0
0
0
[reactos] 01/01: [NETAPI32] Implement NetRegisterDomainNameChangeNotification() and NetUnregisterDomainNameChangeNotification().
by Eric Kohl
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c87482b1df14fbb7f384d…
commit c87482b1df14fbb7f384d884ebc532228a8d00e9 Author: Eric Kohl <eric.kohl(a)reactos.org> AuthorDate: Sat Dec 15 17:17:14 2018 +0100 Commit: Eric Kohl <eric.kohl(a)reactos.org> CommitDate: Sat Dec 15 17:18:32 2018 +0100 [NETAPI32] Implement NetRegisterDomainNameChangeNotification() and NetUnregisterDomainNameChangeNotification(). --- dll/win32/netapi32/misc.c | 52 ++++++++++++++++++++++++++++++++++++++++ dll/win32/netapi32/netapi32.spec | 4 ++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/dll/win32/netapi32/misc.c b/dll/win32/netapi32/misc.c index 650068fa96..0d236e2ed4 100644 --- a/dll/win32/netapi32/misc.c +++ b/dll/win32/netapi32/misc.c @@ -18,6 +18,38 @@ WINE_DEFAULT_DEBUG_CHANNEL(netapi32); /* FUNCTIONS *****************************************************************/ +NET_API_STATUS +WINAPI +NetRegisterDomainNameChangeNotification( + _Out_ PHANDLE NotificationEventHandle) +{ + HANDLE EventHandle; + NTSTATUS Status; + + TRACE("NetRegisterDomainNameChangeNotification(%p)\n", + NotificationEventHandle); + + if (NotificationEventHandle == NULL) + return ERROR_INVALID_PARAMETER; + + EventHandle = CreateEventW(NULL, FALSE, FALSE, NULL); + if (EventHandle == NULL) + return GetLastError(); + + Status = LsaRegisterPolicyChangeNotification(PolicyNotifyDnsDomainInformation, + NotificationEventHandle); + if (!NT_SUCCESS(Status)) + { + CloseHandle(EventHandle); + return NetpNtStatusToApiStatus(Status); + } + + *NotificationEventHandle = EventHandle; + + return NERR_Success; +} + + NET_API_STATUS WINAPI NetStatisticsGet( @@ -83,6 +115,26 @@ NetStatisticsGet( } +NET_API_STATUS +WINAPI +NetUnregisterDomainNameChangeNotification( + _In_ HANDLE NotificationEventHandle) +{ + NTSTATUS Status; + + TRACE("NetUnregisterDomainNameChangeNotification(%p)\n", + NotificationEventHandle); + + if (NotificationEventHandle == NULL) + return ERROR_INVALID_PARAMETER; + + Status = LsaUnregisterPolicyChangeNotification(PolicyNotifyDnsDomainInformation, + NotificationEventHandle); + + return NetpNtStatusToApiStatus(Status); +} + + NET_API_STATUS WINAPI NetpNtStatusToApiStatus( diff --git a/dll/win32/netapi32/netapi32.spec b/dll/win32/netapi32/netapi32.spec index d573ef5fa6..dda3b36b6e 100644 --- a/dll/win32/netapi32/netapi32.spec +++ b/dll/win32/netapi32/netapi32.spec @@ -181,7 +181,7 @@ @ stdcall NetMessageNameEnum(wstr long ptr long ptr ptr ptr) @ stdcall NetMessageNameGetInfo(wstr wstr long ptr) @ stdcall NetQueryDisplayInformation(wstr long long long long ptr ptr) -@ stub NetRegisterDomainNameChangeNotification +@ stdcall NetRegisterDomainNameChangeNotification(ptr) @ stub NetRemoteComputerSupports @ stdcall NetRemoteTOD(wstr ptr) @ stdcall NetRemoveAlternateComputerName(wstr wstr wstr wstr long) @@ -234,7 +234,7 @@ @ stdcall NetShareSetInfo(wstr wstr long ptr ptr) @ stdcall NetStatisticsGet(wstr wstr long long ptr) @ stdcall NetUnjoinDomain(wstr wstr wstr long) -@ stub NetUnregisterDomainNameChangeNotification +@ stdcall NetUnregisterDomainNameChangeNotification(ptr) @ stdcall NetUseAdd(wstr long ptr ptr) @ stdcall NetUseDel(wstr wstr long) @ stdcall NetUseEnum(wstr long ptr long ptr ptr ptr)
5 years, 10 months
1
0
0
0
[reactos] 05/05: [MAINTAINERS][DOC] Update mspatcha in README.WINE and MAINTAINERS
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5f235cc0cb4d019651e78…
commit 5f235cc0cb4d019651e78bf3dbd89c7434b65c81 Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Wed Dec 12 20:07:05 2018 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Dec 15 16:28:59 2018 +0100 [MAINTAINERS][DOC] Update mspatcha in README.WINE and MAINTAINERS --- MAINTAINERS | 5 +++++ media/doc/README.WINE | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 84334c354f..eb6a73707e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -100,6 +100,11 @@ CMake Build Scripts F: */CMakeLists.txt F: */*.cmake +File Patch API + M: learn-more, learn_more, Mark Jansen + S: Maintained + F: dll/win32/mspatcha + File Systems M: HeisSpiter, Pierre Schweitzer S: Maintained diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 03609ea0f7..9b59c155a3 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -118,7 +118,7 @@ reactos/dll/win32/msimtf # Synced to WineStaging-3.3 reactos/dll/win32/msisip # Synced to WineStaging-3.3 reactos/dll/win32/msisys.ocx # Synced to WineStaging-3.3 reactos/dll/win32/msnet32 # Synced to WineStaging-2.9 -reactos/dll/win32/mspatcha # Synced to WineStaging-3.3 +reactos/dll/win32/mspatcha # Forked at WineStaging-3.3 reactos/dll/win32/msrle32 # Synced to WineStaging-3.3 reactos/dll/win32/mssign32 # Synced to WineStaging-3.3 reactos/dll/win32/mssip32 # Synced to WineStaging-3.3
5 years, 10 months
1
0
0
0
[reactos] 04/05: [MSPATCHA] Initial patch decoding + applying. Some initial work is done, all testcases pass now. However a lot of the patch format is still unknown / not working, so do not expect anything other than the apitest to work yet. The next thing to do now, is to gather input, output and patch files, and analyze how the compression and patching works on bigger / more complex files. CORE-15417
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=97d7206f8ba43bd238725…
commit 97d7206f8ba43bd2387253478a40f9d377d7efb1 Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Sat Dec 8 23:49:57 2018 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Dec 15 16:28:59 2018 +0100 [MSPATCHA] Initial patch decoding + applying. Some initial work is done, all testcases pass now. However a lot of the patch format is still unknown / not working, so do not expect anything other than the apitest to work yet. The next thing to do now, is to gather input, output and patch files, and analyze how the compression and patching works on bigger / more complex files. CORE-15417 --- dll/win32/mspatcha/CMakeLists.txt | 2 + dll/win32/mspatcha/lzx.c | 834 +++++++++++++++++++++++++++++++++++++ dll/win32/mspatcha/lzx.h | 60 +++ dll/win32/mspatcha/mspatcha_main.c | 383 ++++++++++++++++- sdk/include/psdk/patchapi.h | 5 + 5 files changed, 1263 insertions(+), 21 deletions(-) diff --git a/dll/win32/mspatcha/CMakeLists.txt b/dll/win32/mspatcha/CMakeLists.txt index d43b046c8b..3c21db607d 100644 --- a/dll/win32/mspatcha/CMakeLists.txt +++ b/dll/win32/mspatcha/CMakeLists.txt @@ -5,6 +5,8 @@ spec2def(mspatcha.dll mspatcha.spec ADD_IMPORTLIB) list(APPEND SOURCE mspatcha_main.c + lzx.c + lzx.h ${CMAKE_CURRENT_BINARY_DIR}/mspatcha_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/mspatcha.def) diff --git a/dll/win32/mspatcha/lzx.c b/dll/win32/mspatcha/lzx.c new file mode 100644 index 0000000000..01a9492411 --- /dev/null +++ b/dll/win32/mspatcha/lzx.c @@ -0,0 +1,834 @@ +/*************************************************************************** + * lzx.c - LZX decompression routines * + * ------------------- * + * * + * maintainer: Jed Wing <jedwin(a)ugcs.caltech.edu> * + * source: modified lzx.c from cabextract v0.5 * + * notes: This file was taken from cabextract v0.5, which was, * + * itself, a modified version of the lzx decompression code * + * from unlzx. * + * * + * platforms: In its current incarnation, this file has been tested on * + * two different Linux platforms (one, redhat-based, with a * + * 2.1.2 glibc and gcc 2.95.x, and the other, Debian, with * + * 2.2.4 glibc and both gcc 2.95.4 and gcc 3.0.2). Both were * + * Intel x86 compatible machines. * + ***************************************************************************/ + +/*************************************************************************** + * + * Copyright(C) Stuart Caie + * + * 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 "lzx.h" +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "windef.h" +#include "winbase.h" + +/* sized types */ +typedef unsigned char UBYTE; /* 8 bits exactly */ +typedef unsigned short UWORD; /* 16 bits (or more) */ + +/* some constants defined by the LZX specification */ +#define LZX_MIN_MATCH (2) +#define LZX_MAX_MATCH (257) +#define LZX_NUM_CHARS (256) +#define LZX_BLOCKTYPE_INVALID (0) /* also blocktypes 4-7 invalid */ +#define LZX_BLOCKTYPE_VERBATIM (1) +#define LZX_BLOCKTYPE_ALIGNED (2) +#define LZX_BLOCKTYPE_UNCOMPRESSED (3) +#define LZX_PRETREE_NUM_ELEMENTS (20) +#define LZX_ALIGNED_NUM_ELEMENTS (8) /* aligned offset tree #elements */ +#define LZX_NUM_PRIMARY_LENGTHS (7) /* this one missing from spec! */ +#define LZX_NUM_SECONDARY_LENGTHS (249) /* length tree #elements */ + +/* LZX huffman defines: tweak tablebits as desired */ +#define LZX_PRETREE_MAXSYMBOLS (LZX_PRETREE_NUM_ELEMENTS) +#define LZX_PRETREE_TABLEBITS (6) +#define LZX_MAINTREE_MAXSYMBOLS (LZX_NUM_CHARS + 50*8) +#define LZX_MAINTREE_TABLEBITS (12) +#define LZX_LENGTH_MAXSYMBOLS (LZX_NUM_SECONDARY_LENGTHS+1) +#define LZX_LENGTH_TABLEBITS (12) +#define LZX_ALIGNED_MAXSYMBOLS (LZX_ALIGNED_NUM_ELEMENTS) +#define LZX_ALIGNED_TABLEBITS (7) + +#define LZX_LENTABLE_SAFETY (64) /* we allow length table decoding overruns */ + +#define LZX_DECLARE_TABLE(tbl) \ + UWORD tbl##_table[(1<<LZX_##tbl##_TABLEBITS) + (LZX_##tbl##_MAXSYMBOLS<<1)];\ + UBYTE tbl##_len [LZX_##tbl##_MAXSYMBOLS + LZX_LENTABLE_SAFETY] + +struct LZXstate +{ + UBYTE *window; /* the actual decoding window */ + ULONG window_size; /* window size (32Kb through 2Mb) */ + ULONG actual_size; /* window size when it was first allocated */ + ULONG window_posn; /* current offset within the window */ + ULONG R0, R1, R2; /* for the LRU offset system */ + UWORD main_elements; /* number of main tree elements */ + int header_read; /* have we started decoding at all yet? */ + UWORD block_type; /* type of this block */ + ULONG block_length; /* uncompressed length of this block */ + ULONG block_remaining; /* uncompressed bytes still left to decode */ + ULONG frames_read; /* the number of CFDATA blocks processed */ + LONG intel_filesize; /* magic header value used for transform */ + LONG intel_curpos; /* current offset in transform space */ + int intel_started; /* have we seen any translatable data yet? */ + + LZX_DECLARE_TABLE(PRETREE); + LZX_DECLARE_TABLE(MAINTREE); + LZX_DECLARE_TABLE(LENGTH); + LZX_DECLARE_TABLE(ALIGNED); +}; + +/* LZX decruncher */ + +/* Microsoft's LZX document and their implementation of the + * com.ms.util.cab Java package do not concur. + * + * In the LZX document, there is a table showing the correlation between + * window size and the number of position slots. It states that the 1MB + * window = 40 slots and the 2MB window = 42 slots. In the implementation, + * 1MB = 42 slots, 2MB = 50 slots. The actual calculation is 'find the + * first slot whose position base is equal to or more than the required + * window size'. This would explain why other tables in the document refer + * to 50 slots rather than 42. + * + * The constant NUM_PRIMARY_LENGTHS used in the decompression pseudocode + * is not defined in the specification. + * + * The LZX document does not state the uncompressed block has an + * uncompressed length field. Where does this length field come from, so + * we can know how large the block is? The implementation has it as the 24 + * bits following after the 3 blocktype bits, before the alignment + * padding. + * + * The LZX document states that aligned offset blocks have their aligned + * offset huffman tree AFTER the main and length trees. The implementation + * suggests that the aligned offset tree is BEFORE the main and length + * trees. + * + * The LZX document decoding algorithm states that, in an aligned offset + * block, if an extra_bits value is 1, 2 or 3, then that number of bits + * should be read and the result added to the match offset. This is + * correct for 1 and 2, but not 3, where just a huffman symbol (using the + * aligned tree) should be read. + * + * Regarding the E8 preprocessing, the LZX document states 'No translation + * may be performed on the last 6 bytes of the input block'. This is + * correct. However, the pseudocode provided checks for the *E8 leader* + * up to the last 6 bytes. If the leader appears between -10 and -7 bytes + * from the end, this would cause the next four bytes to be modified, at + * least one of which would be in the last 6 bytes, which is not allowed + * according to the spec. + * + * The specification states that the huffman trees must always contain at + * least one element. However, many CAB files contain blocks where the + * length tree is completely empty (because there are no matches), and + * this is expected to succeed. + */ + + +/* LZX uses what it calls 'position slots' to represent match offsets. + * What this means is that a small 'position slot' number and a small + * offset from that slot are encoded instead of one large offset for + * every match. + * - position_base is an index to the position slot bases + * - extra_bits states how many bits of offset-from-base data is needed. + */ +static const UBYTE extra_bits[51] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, + 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17 +}; + +static const ULONG position_base[51] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, + 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, + 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360, 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936, + 1835008, 1966080, 2097152 +}; + +struct LZXstate *LZXinit(int window) +{ + struct LZXstate *pState=NULL; + ULONG wndsize = 1 << window; + int i, posn_slots; + + /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */ + /* if a previously allocated window is big enough, keep it */ + if (window < 15 || window > 21) return NULL; + + /* allocate state and associated window */ + pState = HeapAlloc(GetProcessHeap(), 0, sizeof(struct LZXstate)); + if (!(pState->window = HeapAlloc(GetProcessHeap(), 0, wndsize))) + { + HeapFree(GetProcessHeap(), 0, pState); + return NULL; + } + pState->actual_size = wndsize; + pState->window_size = wndsize; + + /* calculate required position slots */ + if (window == 20) posn_slots = 42; + else if (window == 21) posn_slots = 50; + else posn_slots = window << 1; + + /** alternatively **/ + /* posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */ + + /* initialize other state */ + pState->R0 = pState->R1 = pState->R2 = 1; + pState->main_elements = LZX_NUM_CHARS + (posn_slots << 3); + pState->header_read = 0; + pState->frames_read = 0; + pState->block_remaining = 0; + pState->block_type = LZX_BLOCKTYPE_INVALID; + pState->intel_curpos = 0; + pState->intel_started = 0; + pState->window_posn = 0; + + /* initialise tables to 0 (because deltas will be applied to them) */ + for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) pState->MAINTREE_len[i] = 0; + for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) pState->LENGTH_len[i] = 0; + + return pState; +} + +void LZXteardown(struct LZXstate *pState) +{ + if (pState) + { + HeapFree(GetProcessHeap(), 0, pState->window); + HeapFree(GetProcessHeap(), 0, pState); + } +} + +int LZXreset(struct LZXstate *pState) +{ + int i; + + pState->R0 = pState->R1 = pState->R2 = 1; + pState->header_read = 0; + pState->frames_read = 0; + pState->block_remaining = 0; + pState->block_type = LZX_BLOCKTYPE_INVALID; + pState->intel_curpos = 0; + pState->intel_started = 0; + pState->window_posn = 0; + + for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState->MAINTREE_len[i] = 0; + for (i = 0; i < LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY; i++) pState->LENGTH_len[i] = 0; + + return DECR_OK; +} + + +/* Bitstream reading macros: + * + * INIT_BITSTREAM should be used first to set up the system + * READ_BITS(var,n) takes N bits from the buffer and puts them in var + * + * ENSURE_BITS(n) ensures there are at least N bits in the bit buffer + * PEEK_BITS(n) extracts (without removing) N bits from the bit buffer + * REMOVE_BITS(n) removes N bits from the bit buffer + * + * These bit access routines work by using the area beyond the MSB and the + * LSB as a free source of zeroes. This avoids having to mask any bits. + * So we have to know the bit width of the bitbuffer variable. This is + * sizeof(ULONG) * 8, also defined as ULONG_BITS + */ + +/* number of bits in ULONG. Note: This must be at multiple of 16, and at + * least 32 for the bitbuffer code to work (ie, it must be able to ensure + * up to 17 bits - that's adding 16 bits when there's one bit left, or + * adding 32 bits when there are no bits left. The code should work fine + * for machines where ULONG >= 32 bits. + */ +#define ULONG_BITS (sizeof(ULONG)<<3) + +#define INIT_BITSTREAM do { bitsleft = 0; bitbuf = 0; } while (0) + +#define ENSURE_BITS(n) \ + while (bitsleft < (n)) { \ + bitbuf |= ((inpos[1]<<8)|inpos[0]) << (ULONG_BITS-16 - bitsleft); \ + bitsleft += 16; inpos+=2; \ + } + +#define PEEK_BITS(n) (bitbuf >> (ULONG_BITS - (n))) +#define REMOVE_BITS(n) ((bitbuf <<= (n)), (bitsleft -= (n))) + +#define READ_BITS(v,n) do { \ + ENSURE_BITS(n); \ + (v) = PEEK_BITS(n); \ + REMOVE_BITS(n); \ +} while (0) + + +/* Huffman macros */ + +#define TABLEBITS(tbl) (LZX_##tbl##_TABLEBITS) +#define MAXSYMBOLS(tbl) (LZX_##tbl##_MAXSYMBOLS) +#define SYMTABLE(tbl) (pState->tbl##_table) +#define LENTABLE(tbl) (pState->tbl##_len) + +/* BUILD_TABLE(tablename) builds a huffman lookup table from code lengths. + * In reality, it just calls make_decode_table() with the appropriate + * values - they're all fixed by some #defines anyway, so there's no point + * writing each call out in full by hand. + */ +#define BUILD_TABLE(tbl) \ + if (make_decode_table( \ + MAXSYMBOLS(tbl), TABLEBITS(tbl), LENTABLE(tbl), SYMTABLE(tbl) \ + )) { return DECR_ILLEGALDATA; } + + +/* READ_HUFFSYM(tablename, var) decodes one huffman symbol from the + * bitstream using the stated table and puts it in var. + */ +#define READ_HUFFSYM(tbl,var) do { \ + ENSURE_BITS(16); \ + hufftbl = SYMTABLE(tbl); \ + if ((i = hufftbl[PEEK_BITS(TABLEBITS(tbl))]) >= MAXSYMBOLS(tbl)) { \ + j = 1 << (ULONG_BITS - TABLEBITS(tbl)); \ + do { \ + j >>= 1; i <<= 1; i |= (bitbuf & j) ? 1 : 0; \ + if (!j) { return DECR_ILLEGALDATA; } \ + } while ((i = hufftbl[i]) >= MAXSYMBOLS(tbl)); \ + } \ + j = LENTABLE(tbl)[(var) = i]; \ + REMOVE_BITS(j); \ +} while (0) + + +/* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols + * first to last in the given table. The code lengths are stored in their + * own special LZX way. + */ +#define READ_LENGTHS(tbl,first,last) do { \ + lb.bb = bitbuf; lb.bl = bitsleft; lb.ip = inpos; \ + if (lzx_read_lens(pState, LENTABLE(tbl),(first),(last),&lb)) { \ + return DECR_ILLEGALDATA; \ + } \ + bitbuf = lb.bb; bitsleft = lb.bl; inpos = lb.ip; \ +} while (0) + + +/* make_decode_table(nsyms, nbits, length[], table[]) + * + * This function was coded by David Tritscher. It builds a fast huffman + * decoding table out of just a canonical huffman code lengths table. + * + * nsyms = total number of symbols in this huffman tree. + * nbits = any symbols with a code length of nbits or less can be decoded + * in one lookup of the table. + * length = A table to get code lengths from [0 to syms-1] + * table = The table to fill up with decoded symbols and pointers. + * + * Returns 0 for OK or 1 for error + */ + +static int make_decode_table(ULONG nsyms, ULONG nbits, UBYTE *length, UWORD *table) { + register UWORD sym; + register ULONG leaf; + register UBYTE bit_num = 1; + ULONG fill; + ULONG pos = 0; /* the current position in the decode table */ + ULONG table_mask = 1 << nbits; + ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */ + ULONG next_symbol = bit_mask; /* base of allocation for long codes */ + + /* fill entries for codes short enough for a direct mapping */ + while (bit_num <= nbits) { + for (sym = 0; sym < nsyms; sym++) { + if (length[sym] == bit_num) { + leaf = pos; + + if((pos += bit_mask) > table_mask) return 1; /* table overrun */ + + /* fill all possible lookups of this symbol with the symbol itself */ + fill = bit_mask; + while (fill-- > 0) table[leaf++] = sym; + } + } + bit_mask >>= 1; + bit_num++; + } + + /* if there are any codes longer than nbits */ + if (pos != table_mask) { + /* clear the remainder of the table */ + for (sym = pos; sym < table_mask; sym++) table[sym] = 0; + + /* give ourselves room for codes to grow by up to 16 more bits */ + pos <<= 16; + table_mask <<= 16; + bit_mask = 1 << 15; + + while (bit_num <= 16) { + for (sym = 0; sym < nsyms; sym++) { + if (length[sym] == bit_num) { + leaf = pos >> 16; + for (fill = 0; fill < bit_num - nbits; fill++) { + /* if this path hasn't been taken yet, 'allocate' two entries */ + if (table[leaf] == 0) { + table[(next_symbol << 1)] = 0; + table[(next_symbol << 1) + 1] = 0; + table[leaf] = next_symbol++; + } + /* follow the path and select either left or right for next bit */ + leaf = table[leaf] << 1; + if ((pos >> (15-fill)) & 1) leaf++; + } + table[leaf] = sym; + + if ((pos += bit_mask) > table_mask) return 1; /* table overflow */ + } + } + bit_mask >>= 1; + bit_num++; + } + } + + /* full table? */ + if (pos == table_mask) return 0; + + /* either erroneous table, or all elements are 0 - let's find out. */ + for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1; + return 0; +} + +struct lzx_bits { + ULONG bb; + int bl; + UBYTE *ip; +}; + +static int lzx_read_lens(struct LZXstate *pState, UBYTE *lens, ULONG first, ULONG last, struct lzx_bits *lb) { + ULONG i,j, x,y; + int z; + + register ULONG bitbuf = lb->bb; + register int bitsleft = lb->bl; + UBYTE *inpos = lb->ip; + UWORD *hufftbl; + + for (x = 0; x < 20; x++) { + READ_BITS(y, 4); + LENTABLE(PRETREE)[x] = y; + } + BUILD_TABLE(PRETREE); + + for (x = first; x < last; ) { + READ_HUFFSYM(PRETREE, z); + if (z == 17) { + READ_BITS(y, 4); y += 4; + while (y--) lens[x++] = 0; + } + else if (z == 18) { + READ_BITS(y, 5); y += 20; + while (y--) lens[x++] = 0; + } + else if (z == 19) { + READ_BITS(y, 1); y += 4; + READ_HUFFSYM(PRETREE, z); + z = lens[x] - z; if (z < 0) z += 17; + while (y--) lens[x++] = z; + } + else { + z = lens[x] - z; if (z < 0) z += 17; + lens[x++] = z; + } + } + + lb->bb = bitbuf; + lb->bl = bitsleft; + lb->ip = inpos; + return 0; +} + +int LZXdecompress(struct LZXstate *pState, unsigned char *inpos, unsigned char *outpos, int inlen, int outlen) { + UBYTE *endinp = inpos + inlen; + UBYTE *window = pState->window; + UBYTE *runsrc, *rundest; + UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */ + + ULONG window_posn = pState->window_posn; + ULONG window_size = pState->window_size; + ULONG R0 = pState->R0; + ULONG R1 = pState->R1; + ULONG R2 = pState->R2; + + register ULONG bitbuf; + register int bitsleft; + ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */ + struct lzx_bits lb; /* used in READ_LENGTHS macro */ + + int togo = outlen, this_run, main_element, aligned_bits; + int match_length, length_footer, extra, verbatim_bits; + int copy_length; + + INIT_BITSTREAM; + + /* read header if necessary */ + if (!pState->header_read) { + i = j = 0; + READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); } + pState->intel_filesize = (i << 16) | j; /* or 0 if not encoded */ + pState->header_read = 1; + } + + /* main decoding loop */ + while (togo > 0) { + /* last block finished, new block expected */ + if (pState->block_remaining == 0) { + if (pState->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) { + if (pState->block_length & 1) inpos++; /* realign bitstream to word */ + INIT_BITSTREAM; + } + + READ_BITS(pState->block_type, 3); + READ_BITS(i, 16); + READ_BITS(j, 8); + pState->block_remaining = pState->block_length = (i << 8) | j; + + switch (pState->block_type) { + case LZX_BLOCKTYPE_ALIGNED: + for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; } + BUILD_TABLE(ALIGNED); + /* rest of aligned header is same as verbatim */ + + case LZX_BLOCKTYPE_VERBATIM: + READ_LENGTHS(MAINTREE, 0, 256); + READ_LENGTHS(MAINTREE, 256, pState->main_elements); + BUILD_TABLE(MAINTREE); + if (LENTABLE(MAINTREE)[0xE8] != 0) pState->intel_started = 1; + + READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); + BUILD_TABLE(LENGTH); + break; + + case LZX_BLOCKTYPE_UNCOMPRESSED: + pState->intel_started = 1; /* because we can't assume otherwise */ + ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */ + if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */ + R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4; + R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4; + R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4; + break; + + default: + return DECR_ILLEGALDATA; + } + } + + /* buffer exhaustion check */ + if (inpos > endinp) { + /* it's possible to have a file where the next run is less than + * 16 bits in size. In this case, the READ_HUFFSYM() macro used + * in building the tables will exhaust the buffer, so we should + * allow for this, but not allow those accidentally read bits to + * be used (so we check that there are at least 16 bits + * remaining - in this boundary case they aren't really part of + * the compressed data) + */ + if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA; + } + + while ((this_run = pState->block_remaining) > 0 && togo > 0) { + if (this_run > togo) this_run = togo; + togo -= this_run; + pState->block_remaining -= this_run; + + /* apply 2^x-1 mask */ + window_posn &= window_size - 1; + /* runs can't straddle the window wraparound */ + if ((window_posn + this_run) > window_size) + return DECR_DATAFORMAT; + + switch (pState->block_type) { + + case LZX_BLOCKTYPE_VERBATIM: + while (this_run > 0) { + READ_HUFFSYM(MAINTREE, main_element); + + if (main_element < LZX_NUM_CHARS) { + /* literal: 0 to LZX_NUM_CHARS-1 */ + window[window_posn++] = main_element; + this_run--; + } + else { + /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ + main_element -= LZX_NUM_CHARS; + + match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; + if (match_length == LZX_NUM_PRIMARY_LENGTHS) { + READ_HUFFSYM(LENGTH, length_footer); + match_length += length_footer; + } + match_length += LZX_MIN_MATCH; + + match_offset = main_element >> 3; + + if (match_offset > 2) { + /* not repeated offset */ + if (match_offset != 3) { + extra = extra_bits[match_offset]; + READ_BITS(verbatim_bits, extra); + match_offset = position_base[match_offset] - 2 + verbatim_bits; + } + else { + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = match_offset; + } + else if (match_offset == 0) { + match_offset = R0; + } + else if (match_offset == 1) { + match_offset = R1; + R1 = R0; R0 = match_offset; + } + else /* match_offset == 2 */ { + match_offset = R2; + R2 = R0; R0 = match_offset; + } + + rundest = window + window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (window_posn >= match_offset) { + /* no wrap */ + runsrc = rundest - match_offset; + } else { + runsrc = rundest + (window_size - match_offset); + copy_length = match_offset - window_posn; + if (copy_length < match_length) { + match_length -= copy_length; + window_posn += copy_length; + while (copy_length-- > 0) *rundest++ = *runsrc++; + runsrc = window; + } + } + window_posn += match_length; + + /* copy match data - no worries about destination wraps */ + while (match_length-- > 0) *rundest++ = *runsrc++; + + } + } + break; + + case LZX_BLOCKTYPE_ALIGNED: + while (this_run > 0) { + READ_HUFFSYM(MAINTREE, main_element); + + if (main_element < LZX_NUM_CHARS) { + /* literal: 0 to LZX_NUM_CHARS-1 */ + window[window_posn++] = main_element; + this_run--; + } + else { + /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ + main_element -= LZX_NUM_CHARS; + + match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; + if (match_length == LZX_NUM_PRIMARY_LENGTHS) { + READ_HUFFSYM(LENGTH, length_footer); + match_length += length_footer; + } + match_length += LZX_MIN_MATCH; + + match_offset = main_element >> 3; + + if (match_offset > 2) { + /* not repeated offset */ + extra = extra_bits[match_offset]; + match_offset = position_base[match_offset] - 2; + if (extra > 3) { + /* verbatim and aligned bits */ + extra -= 3; + READ_BITS(verbatim_bits, extra); + match_offset += (verbatim_bits << 3); + READ_HUFFSYM(ALIGNED, aligned_bits); + match_offset += aligned_bits; + } + else if (extra == 3) { + /* aligned bits only */ + READ_HUFFSYM(ALIGNED, aligned_bits); + match_offset += aligned_bits; + } + else if (extra > 0) { /* extra==1, extra==2 */ + /* verbatim bits only */ + READ_BITS(verbatim_bits, extra); + match_offset += verbatim_bits; + } + else /* extra == 0 */ { + /* ??? */ + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = match_offset; + } + else if (match_offset == 0) { + match_offset = R0; + } + else if (match_offset == 1) { + match_offset = R1; + R1 = R0; R0 = match_offset; + } + else /* match_offset == 2 */ { + match_offset = R2; + R2 = R0; R0 = match_offset; + } + + rundest = window + window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (window_posn >= match_offset) { + /* no wrap */ + runsrc = rundest - match_offset; + } else { + runsrc = rundest + (window_size - match_offset); + copy_length = match_offset - window_posn; + if (copy_length < match_length) { + match_length -= copy_length; + window_posn += copy_length; + while (copy_length-- > 0) *rundest++ = *runsrc++; + runsrc = window; + } + } + window_posn += match_length; + + /* copy match data - no worries about destination wraps */ + while (match_length-- > 0) *rundest++ = *runsrc++; + + } + } + break; + + case LZX_BLOCKTYPE_UNCOMPRESSED: + if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA; + memcpy(window + window_posn, inpos, (size_t) this_run); + inpos += this_run; window_posn += this_run; + break; + + default: + return DECR_ILLEGALDATA; /* might as well */ + } + + } + } + + if (togo != 0) return DECR_ILLEGALDATA; + memcpy(outpos, window + ((!window_posn) ? window_size : window_posn) - outlen, (size_t) outlen); + + pState->window_posn = window_posn; + pState->R0 = R0; + pState->R1 = R1; + pState->R2 = R2; + + /* intel E8 decoding */ + if ((pState->frames_read++ < 32768) && pState->intel_filesize != 0) { + if (outlen <= 6 || !pState->intel_started) { + pState->intel_curpos += outlen; + } + else { + UBYTE *data = outpos; + UBYTE *dataend = data + outlen - 10; + LONG curpos = pState->intel_curpos; + LONG filesize = pState->intel_filesize; + LONG abs_off, rel_off; + + pState->intel_curpos = curpos + outlen; + + while (data < dataend) { + if (*data++ != 0xE8) { curpos++; continue; } + abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); + if ((abs_off >= -curpos) && (abs_off < filesize)) { + rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; + data[0] = (UBYTE) rel_off; + data[1] = (UBYTE) (rel_off >> 8); + data[2] = (UBYTE) (rel_off >> 16); + data[3] = (UBYTE) (rel_off >> 24); + } + data += 4; + curpos += 5; + } + } + } + return DECR_OK; +} + +#ifdef LZX_CHM_TESTDRIVER +int main(int c, char **v) +{ + FILE *fin, *fout; + struct LZXstate state; + UBYTE ibuf[16384]; + UBYTE obuf[32768]; + int ilen, olen; + int status; + int i; + int count=0; + int w = atoi(v[1]); + LZXinit(&state, w); + fout = fopen(v[2], "wb"); + for (i=3; i<c; i++) + { + fin = fopen(v[i], "rb"); + ilen = fread(ibuf, 1, 16384, fin); + status = LZXdecompress(&state, ibuf, obuf, ilen, 32768); + switch (status) + { + case DECR_OK: + printf("ok\n"); + fwrite(obuf, 1, 32768, fout); + break; + case DECR_DATAFORMAT: + printf("bad format\n"); + break; + case DECR_ILLEGALDATA: + printf("illegal data\n"); + break; + case DECR_NOMEMORY: + printf("no memory\n"); + break; + default: + break; + } + fclose(fin); + if (++count == 2) + { + count = 0; + LZXreset(&state); + } + } + fclose(fout); +} +#endif diff --git a/dll/win32/mspatcha/lzx.h b/dll/win32/mspatcha/lzx.h new file mode 100644 index 0000000000..8590307979 --- /dev/null +++ b/dll/win32/mspatcha/lzx.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * lzx.h - LZX decompression routines * + * ------------------- * + * * + * maintainer: Jed Wing <jedwin(a)ugcs.caltech.edu> * + * source: modified lzx.c from cabextract v0.5 * + * notes: This file was taken from cabextract v0.5, which was, * + * itself, a modified version of the lzx decompression code * + * from unlzx. * + ***************************************************************************/ + +/*************************************************************************** + * + * Copyright(C) Stuart Caie + * + * 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 + * + ***************************************************************************/ + +#ifndef INCLUDED_LZX_H +#define INCLUDED_LZX_H + +/* return codes */ +#define DECR_OK (0) +#define DECR_DATAFORMAT (1) +#define DECR_ILLEGALDATA (2) +#define DECR_NOMEMORY (3) + +/* opaque state structure */ +struct LZXstate; + +/* create an lzx state object */ +struct LZXstate *LZXinit(int window); + +/* destroy an lzx state object */ +void LZXteardown(struct LZXstate *pState); + +/* reset an lzx stream */ +int LZXreset(struct LZXstate *pState); + +/* decompress an LZX compressed block */ +int LZXdecompress(struct LZXstate *pState, + unsigned char *inpos, + unsigned char *outpos, + int inlen, + int outlen); + +#endif /* INCLUDED_LZX_H */ diff --git a/dll/win32/mspatcha/mspatcha_main.c b/dll/win32/mspatcha/mspatcha_main.c index 4ad198873e..19e2677f39 100644 --- a/dll/win32/mspatcha/mspatcha_main.c +++ b/dll/win32/mspatcha/mspatcha_main.c @@ -2,6 +2,7 @@ * PatchAPI * * Copyright 2011 David Hedberg for CodeWeavers + * Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,27 +25,200 @@ #include "winnls.h" #include "ndk/rtlfuncs.h" #include "patchapi.h" +#include "lzx.h" #include "wine/debug.h" static const char szHexString[] = "0123456789abcdef"; #define SIGNATURE_MIN_SIZE 9 +#define UNKNOWN_FLAGS_COMBINATION 0x00c40001 + + WINE_DEFAULT_DEBUG_CHANNEL(mspatcha); + +typedef struct _SAFE_READ +{ + PBYTE Root; + DWORD Size; + PBYTE Ptr; +} SAFE_READ, *PSAFE_READ; + + +/** + * @name ReadByte + * Read the next byte available from @param pRead + * + * @param pRead + * The input buffer + * + * @return The byte, or 0 + */ +BYTE ReadByte(PSAFE_READ pRead) +{ + if (pRead->Ptr + sizeof(BYTE) <= (pRead->Root + pRead->Size)) + { + BYTE Value = *(PBYTE)pRead->Ptr; + pRead->Ptr += sizeof(BYTE); + return Value; + } + pRead->Ptr = pRead->Root + pRead->Size; + return 0; +} + +/** + * @name ReadUShort + * Read the next unsigned short available from @param pRead + * + * @param pRead + * The input buffer + * + * @return The unsigned short, or 0 + */ +USHORT ReadUShort(PSAFE_READ pRead) +{ + if (pRead->Ptr + sizeof(USHORT) <= (pRead->Root + pRead->Size)) + { + USHORT Value = *(PUSHORT)pRead->Ptr; + pRead->Ptr += sizeof(USHORT); + return Value; + } + pRead->Ptr = pRead->Root + pRead->Size; + return 0; +} + +/** + * @name ReadDWord + * Read the next dword available from @param pRead + * + * @param pRead + * The input buffer + * + * @return The dword, or 0 + */ +DWORD ReadDWord(PSAFE_READ pRead) +{ + if (pRead->Ptr + sizeof(DWORD) <= (pRead->Root + pRead->Size)) + { + DWORD Value = *(PDWORD)pRead->Ptr; + pRead->Ptr += sizeof(DWORD); + return Value; + } + pRead->Ptr = pRead->Root + pRead->Size; + return 0; +} + +/** + * @name DecodeDWord + * Read the next variable length-encoded dword from @param pRead + * + * @param pRead + * The input buffer + * + * @return The dword, or 0 + */ +DWORD DecodeDWord(PSAFE_READ pRead) +{ + UINT Result = 0, offset; + + for (offset = 0; offset < 32; offset += 7) + { + DWORD val = ReadByte(pRead); + Result |= ((val & 0x7f) << offset); + if (val & 0x80) + break; + } + + return Result; +} + + +/** + * @name DecodeInt + * Read the next variable length-encoded int from @param pRead + * + * @param pRead + * The input buffer + * + * @return The int, or 0 + */ +INT DecodeInt(PSAFE_READ pRead) +{ + INT Result = 0, offset; + + for (offset = 0; offset < 32; offset += 6) + { + INT val = (INT)(DWORD)ReadByte(pRead); + Result |= ((val & 0x3f) << offset); + if (val & 0x80) + { + if (val & 0x40) + Result *= -1; + break; + } + } + + return Result; +} + + +typedef struct _PATCH_HEADER +{ + DWORD Flags; + + DWORD ImageBase; + DWORD ImageTimeStamp; + + DWORD OutputSize; + DWORD OutputCrc; + + DWORD OldSize; + DWORD OldCrc; + DWORD DataSize; // Payload after the patch header + +} PATCH_HEADER; + + +/** + * @name MapFile + * Map a view of a file into readonly memory + * + * @param hFile + * The input file handle, readable + * + * @param dwSize + * Mapped file size (out) + * + * @return A Pointer to the start of the memory + */ +static PBYTE MapFile(HANDLE hFile, DWORD* dwSize) +{ + HANDLE hMap; + PVOID pView; + + *dwSize = GetFileSize(hFile, NULL); + hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMap != INVALID_HANDLE_VALUE) + { + pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hMap); + return pView; + } + + return NULL; +} + + /***************************************************** * DllMain (MSPATCHA.@) */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); - switch (fdwReason) { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hinstDLL); - break; + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + break; } return TRUE; @@ -81,15 +255,188 @@ BOOL WINAPI ApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_fil return ret; } + +/** + * @name ParseHeader + * Parse a Patch file header + * @note The current implementation is far from complete! + * + * @param Patch + * Buffer pointing to the raw patch data + * + * @param Header + * The result of the parsed header + * + * @return STATUS_SUCCESS on success, an error code otherwise + */ +DWORD ParseHeader(SAFE_READ* Patch, PATCH_HEADER* Header) +{ + DWORD Crc, Unknown; + int Delta; + + ZeroMemory(Header, sizeof(*Header)); + + /* Validate the patch */ + Crc = RtlComputeCrc32(0, Patch->Root, Patch->Size); + if (Crc != ~0) + return ERROR_PATCH_CORRUPT; + + if (ReadDWord(Patch) != '91AP') + return ERROR_PATCH_DECODE_FAILURE; + + /* Read the flags, warn about an unknown combination */ + Header->Flags = ReadDWord(Patch); + if (Header->Flags ^ UNKNOWN_FLAGS_COMBINATION) + ERR("Unknown flags: 0x%x, patch will most likely fail\n", Header->Flags ^ UNKNOWN_FLAGS_COMBINATION); + + /* 0x5bb3284e, 0x5bb33562, 0x5bb357b1 */ + Unknown = ReadDWord(Patch); + TRACE("Unknown: 0x%x\n", Unknown); + + Header->OutputSize = DecodeDWord(Patch); + Header->OutputCrc = ReadDWord(Patch); + + Unknown = ReadByte(Patch); + if (Unknown != 1) + ERR("Field after CRC is not 1 but %u\n", Unknown); + + Delta = DecodeInt(Patch); + Header->OldSize = Header->OutputSize + Delta; + Header->OldCrc = ReadDWord(Patch); + + Unknown = ReadUShort(Patch); + if (Unknown != 0) + ERR("Field1 after OldCrc is not 0 but %u\n", Unknown); + + Unknown = DecodeDWord(Patch); + if (Unknown != 0) + ERR("Field2 after OldCrc is not 0 but %u\n", Unknown); + + Header->DataSize = DecodeDWord(Patch); + /* Remaining data, minus the CRC appended */ + if (Header->DataSize != (Patch->Size - (Patch->Ptr - Patch->Root) - sizeof(DWORD))) + { + ERR("Unable to read header, check previous logging!\n"); + return ERROR_PATCH_DECODE_FAILURE; + } + return STATUS_SUCCESS; +} + +/** + * @name CreateNewFileFromPatch + * Using the input @param Header and @param Patch, create a new file on @param new_file + * + * @param Header + * Parsed / preprocessed patch header + * + * @param Patch + * Memory buffer pointing to the patch payload + * + * @param new_file + * A handle to the output file. This file will be resized + * + * @return STATUS_SUCCESS on success, an error code otherwise + */ +DWORD CreateNewFileFromPatch(PATCH_HEADER* Header, SAFE_READ* Patch, HANDLE new_file) +{ + SAFE_READ NewFile; + HANDLE hMap; + USHORT BlockSize; + DWORD dwStatus; + struct LZXstate* state; + int lzxResult; + + hMap = CreateFileMappingW(new_file, NULL, PAGE_READWRITE, 0, Header->OutputSize, NULL); + if (hMap == INVALID_HANDLE_VALUE) + return ERROR_PATCH_NOT_AVAILABLE; + + NewFile.Root = NewFile.Ptr = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); + CloseHandle(hMap); + NewFile.Size = Header->OutputSize; + + if (!NewFile.Root) + return ERROR_PATCH_NOT_AVAILABLE; + + /* At this point Patch->Ptr should point to the payload */ + BlockSize = ReadUShort(Patch); + + /* This window size does not work on all files (for example, MS SQL Express 2008 setup) */ + state = LZXinit(17); + if (state) + { + lzxResult = LZXdecompress(state, Patch->Ptr, NewFile.Ptr, BlockSize, NewFile.Size); + LZXteardown(state); + + if (lzxResult == DECR_OK) + dwStatus = STATUS_SUCCESS; + else + dwStatus = ERROR_PATCH_DECODE_FAILURE; + } + else + { + dwStatus = ERROR_INSUFFICIENT_BUFFER; + } + + UnmapViewOfFile(NewFile.Root); + return dwStatus; +} + + /***************************************************** * ApplyPatchToFileByHandles (MSPATCHA.2) */ BOOL WINAPI ApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, HANDLE new_file, ULONG apply_flags) { - FIXME("stub - %p, %p, %p, %08x\n", patch_file, old_file, new_file, apply_flags); + SAFE_READ Patch, OldFile; + DWORD dwStatus; + PATCH_HEADER Header; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + Patch.Root = Patch.Ptr = MapFile(patch_file, &Patch.Size); + if (!Patch.Root) + { + SetLastError(ERROR_PATCH_CORRUPT); + return FALSE; + } + + /* Let's decode the header */ + dwStatus = ParseHeader(&Patch, &Header); + if (dwStatus != STATUS_SUCCESS) + { + UnmapViewOfFile(Patch.Root); + SetLastError(dwStatus); + return FALSE; + } + + OldFile.Root = OldFile.Ptr = MapFile(old_file, &OldFile.Size); + if (OldFile.Root) + { + DWORD dwCrc; + + /* Verify the input file */ + dwCrc = RtlComputeCrc32(0, OldFile.Root, OldFile.Size); + if (OldFile.Size == Header.OldSize && dwCrc == Header.OldCrc) + { + if (apply_flags & APPLY_OPTION_TEST_ONLY) + dwStatus = STATUS_SUCCESS; + else + dwStatus = CreateNewFileFromPatch(&Header, &Patch, new_file); + } + else + { + dwStatus = ERROR_PATCH_WRONG_FILE; + } + UnmapViewOfFile(OldFile.Root); + } + else + { + dwStatus = GetLastError(); + if (dwStatus == STATUS_SUCCESS) + dwStatus = ERROR_PATCH_NOT_AVAILABLE; + } + + UnmapViewOfFile(Patch.Root); + SetLastError(dwStatus); + return dwStatus == STATUS_SUCCESS; } /***************************************************** @@ -153,9 +500,8 @@ BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE hFile, ULONG flags, PVOID data, PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) { BOOL ret = FALSE; - HANDLE hMap; DWORD dwSize, ulCrc; - PVOID pView; + PBYTE pData; if (flags) FIXME("Unhandled flags 0x%x\n", flags); @@ -164,19 +510,14 @@ BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE hFile, ULONG flags, PVOID data, if (retain_range_count) FIXME("Unhandled ignore_range_count %u\n", retain_range_count); - dwSize = GetFileSize(hFile, NULL); - hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (hMap != INVALID_HANDLE_VALUE) + if ((pData = MapFile(hFile, &dwSize))) { - pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hMap); - - if (dwSize >= 2 && *(PWORD)pView == IMAGE_DOS_SIGNATURE) + if (dwSize >= 2 && *(PWORD)pData == IMAGE_DOS_SIGNATURE) { FIXME("Potentially unimplemented case, normalized signature\n"); } - ulCrc = RtlComputeCrc32(0, pView, dwSize); + ulCrc = RtlComputeCrc32(0, pData, dwSize); if (bufsize >= SIGNATURE_MIN_SIZE) { char *pBuffer = buffer; @@ -188,7 +529,7 @@ BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE hFile, ULONG flags, PVOID data, } ret = TRUE; } - UnmapViewOfFile(pView); + UnmapViewOfFile(pData); if (bufsize < SIGNATURE_MIN_SIZE) SetLastError(ERROR_INSUFFICIENT_BUFFER); diff --git a/sdk/include/psdk/patchapi.h b/sdk/include/psdk/patchapi.h index 03853283ac..cf8ee514a5 100644 --- a/sdk/include/psdk/patchapi.h +++ b/sdk/include/psdk/patchapi.h @@ -32,8 +32,13 @@ extern "C" { // // apply error codes // +#define ERROR_PATCH_DECODE_FAILURE 0xC00E4101 #define ERROR_PATCH_CORRUPT 0xC00E4102 +#define ERROR_PATCH_NEWER_FORMAT 0xC00E4103 #define ERROR_PATCH_WRONG_FILE 0xC00E4104 +#define ERROR_PATCH_NOT_NECESSARY 0xC00E4105 +#define ERROR_PATCH_NOT_AVAILABLE 0xC00E4106 + typedef struct _PATCH_IGNORE_RANGE {
5 years, 10 months
1
0
0
0
[reactos] 03/05: [MSPATCHA] Implement GetFilePatchSignature functions
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=33e3a69a7fedc75a3cc98…
commit 33e3a69a7fedc75a3cc988412494233d6b84967a Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Sun Dec 2 19:14:16 2018 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Dec 15 16:28:59 2018 +0100 [MSPATCHA] Implement GetFilePatchSignature functions --- dll/win32/mspatcha/mspatcha.spec | 10 +- dll/win32/mspatcha/mspatcha_main.c | 250 ++++++++++++++++++++++++++++++------- 2 files changed, 211 insertions(+), 49 deletions(-) diff --git a/dll/win32/mspatcha/mspatcha.spec b/dll/win32/mspatcha/mspatcha.spec index 08231e0d6f..cf3d7d6870 100644 --- a/dll/win32/mspatcha/mspatcha.spec +++ b/dll/win32/mspatcha/mspatcha.spec @@ -1,12 +1,12 @@ 1 stdcall ApplyPatchToFileA(str str str long) -2 stdcall -stub ApplyPatchToFileByHandles(ptr ptr ptr long) +2 stdcall ApplyPatchToFileByHandles(ptr ptr ptr long) 3 stub ApplyPatchToFileByHandlesEx 4 stub ApplyPatchToFileExA 5 stub ApplyPatchToFileExW 6 stdcall ApplyPatchToFileW(wstr wstr wstr long) 7 stdcall GetFilePatchSignatureA(str long ptr long ptr long ptr long ptr) -8 stdcall -stub GetFilePatchSignatureByHandle(ptr long ptr long ptr long ptr long ptr) +8 stdcall GetFilePatchSignatureByHandle(ptr long ptr long ptr long ptr long ptr) 9 stdcall GetFilePatchSignatureW(wstr long ptr long ptr long ptr long ptr) -10 stdcall -stub TestApplyPatchToFileA(str str long) -11 stdcall -stub TestApplyPatchToFileByHandles(ptr ptr long) -12 stdcall -stub TestApplyPatchToFileW(wstr wstr long) +10 stdcall TestApplyPatchToFileA(str str long) +11 stdcall TestApplyPatchToFileByHandles(ptr ptr long) +12 stdcall TestApplyPatchToFileW(wstr wstr long) diff --git a/dll/win32/mspatcha/mspatcha_main.c b/dll/win32/mspatcha/mspatcha_main.c index 8dc4403d13..4ad198873e 100644 --- a/dll/win32/mspatcha/mspatcha_main.c +++ b/dll/win32/mspatcha/mspatcha_main.c @@ -18,16 +18,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - -#include <stdarg.h> - +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "winnls.h" +#include "ndk/rtlfuncs.h" #include "patchapi.h" #include "wine/debug.h" +static const char szHexString[] = "0123456789abcdef"; +#define SIGNATURE_MIN_SIZE 9 + WINE_DEFAULT_DEBUG_CHANNEL(mspatcha); /***************************************************** @@ -49,57 +50,79 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } -static inline WCHAR *strdupAW( const char *src ) -{ - WCHAR *dst = NULL; - if (src) - { - int len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 ); - if ((dst = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len ); - } - return dst; -} - /***************************************************** * ApplyPatchToFileA (MSPATCHA.1) */ BOOL WINAPI ApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags) { - BOOL ret; - WCHAR *patch_fileW, *new_fileW, *old_fileW = NULL; + BOOL ret = FALSE; + HANDLE hPatch, hOld, hNew; - if (!(patch_fileW = strdupAW( patch_file ))) return FALSE; - if (old_file && !(old_fileW = strdupAW( old_file ))) + hPatch = CreateFileA(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) { - HeapFree( GetProcessHeap(), 0, patch_fileW ); - return FALSE; + hOld = CreateFileA(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + hNew = CreateFileA(new_file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hNew != INVALID_HANDLE_VALUE) + { + ret = ApplyPatchToFileByHandles(hPatch, hOld, hNew, apply_flags); + CloseHandle(hNew); + } + CloseHandle(hOld); + } + CloseHandle(hPatch); } - if (!(new_fileW = strdupAW( new_file ))) - { - HeapFree( GetProcessHeap(), 0, patch_fileW ); - HeapFree( GetProcessHeap(), 0, old_fileW ); - return FALSE; - } - ret = ApplyPatchToFileW( patch_fileW, old_fileW, new_fileW, apply_flags ); - HeapFree( GetProcessHeap(), 0, patch_fileW ); - HeapFree( GetProcessHeap(), 0, old_fileW ); - HeapFree( GetProcessHeap(), 0, new_fileW ); + return ret; } /***************************************************** - * ApplyPatchToFileW (MSPATCHA.6) + * ApplyPatchToFileByHandles (MSPATCHA.2) */ -BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, LPCWSTR new_file, ULONG apply_flags) +BOOL WINAPI ApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, HANDLE new_file, ULONG apply_flags) { - FIXME("stub - %s, %s, %s, %08x\n", debugstr_w(patch_file), debugstr_w(old_file), - debugstr_w(new_file), apply_flags); + FIXME("stub - %p, %p, %p, %08x\n", patch_file, old_file, new_file, apply_flags); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } +/***************************************************** + * ApplyPatchToFileW (MSPATCHA.6) + */ +BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, LPCWSTR new_file, ULONG apply_flags) +{ + BOOL ret = FALSE; + HANDLE hPatch, hOld, hNew; + + hPatch = CreateFileW(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) + { + hOld = CreateFileW(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + hNew = CreateFileW(new_file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hNew != INVALID_HANDLE_VALUE) + { + ret = ApplyPatchToFileByHandles(hPatch, hOld, hNew, apply_flags); + CloseHandle(hNew); + } + CloseHandle(hOld); + } + CloseHandle(hPatch); + } + + return ret; +} + /***************************************************** * GetFilePatchSignatureA (MSPATCHA.7) */ @@ -107,10 +130,71 @@ BOOL WINAPI GetFilePatchSignatureA(LPCSTR filename, ULONG flags, PVOID data, ULO PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) { - FIXME("stub - %s, %x, %p, %u, %p, %u, %p, %u, %p\n", debugstr_a(filename), flags, data, - ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + BOOL ret = FALSE; + HANDLE hFile; + + hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + ret = GetFilePatchSignatureByHandle(hFile, flags, data, ignore_range_count, ignore_range, + retain_range_count, retain_range, bufsize, buffer); + CloseHandle(hFile); + } + + return ret; +} + +/***************************************************** + * GetFilePatchSignatureA (MSPATCHA.7) + */ +BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE hFile, ULONG flags, PVOID data, ULONG ignore_range_count, + PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, + PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) +{ + BOOL ret = FALSE; + HANDLE hMap; + DWORD dwSize, ulCrc; + PVOID pView; + + if (flags) + FIXME("Unhandled flags 0x%x\n", flags); + if (ignore_range_count) + FIXME("Unhandled ignore_range_count %u\n", ignore_range_count); + if (retain_range_count) + FIXME("Unhandled ignore_range_count %u\n", retain_range_count); + + dwSize = GetFileSize(hFile, NULL); + hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMap != INVALID_HANDLE_VALUE) + { + pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hMap); + + if (dwSize >= 2 && *(PWORD)pView == IMAGE_DOS_SIGNATURE) + { + FIXME("Potentially unimplemented case, normalized signature\n"); + } + + ulCrc = RtlComputeCrc32(0, pView, dwSize); + if (bufsize >= SIGNATURE_MIN_SIZE) + { + char *pBuffer = buffer; + pBuffer[8] = '\0'; + for (dwSize = 0; dwSize < 8; ++dwSize) + { + pBuffer[7 - dwSize] = szHexString[ulCrc & 0xf]; + ulCrc >>= 4; + } + ret = TRUE; + } + UnmapViewOfFile(pView); + + if (bufsize < SIGNATURE_MIN_SIZE) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + + return ret; } /***************************************************** @@ -120,8 +204,86 @@ BOOL WINAPI GetFilePatchSignatureW(LPCWSTR filename, ULONG flags, PVOID data, UL PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) { - FIXME("stub - %s, %x, %p, %u, %p, %u, %p, %u, %p\n", debugstr_w(filename), flags, data, - ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + CHAR LocalBuf[SIGNATURE_MIN_SIZE]; + BOOL ret = FALSE; + HANDLE hFile; + + hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + ret = GetFilePatchSignatureByHandle(hFile, flags, data, ignore_range_count, ignore_range, + retain_range_count, retain_range, sizeof(LocalBuf), LocalBuf); + CloseHandle(hFile); + + if (bufsize < (SIGNATURE_MIN_SIZE * sizeof(WCHAR))) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + if (ret) + { + MultiByteToWideChar(CP_ACP, 0, LocalBuf, -1, buffer, bufsize / sizeof(WCHAR)); + } + } + + return ret; +} + +/***************************************************** + * TestApplyPatchToFileA (MSPATCHA.10) + */ +BOOL WINAPI TestApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, ULONG apply_flags) +{ + BOOL ret = FALSE; + HANDLE hPatch, hOld; + + hPatch = CreateFileA(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) + { + hOld = CreateFileA(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + ret = TestApplyPatchToFileByHandles(hPatch, hOld, apply_flags); + CloseHandle(hOld); + } + CloseHandle(hPatch); + } + + return ret; +} + +/***************************************************** + * TestApplyPatchToFileByHandles (MSPATCHA.11) + */ +BOOL WINAPI TestApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, ULONG apply_flags) +{ + return ApplyPatchToFileByHandles(patch_file, old_file, INVALID_HANDLE_VALUE, apply_flags | APPLY_OPTION_TEST_ONLY); +} + +/***************************************************** + * TestApplyPatchToFileW (MSPATCHA.12) + */ +BOOL WINAPI TestApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, ULONG apply_flags) +{ + BOOL ret = FALSE; + HANDLE hPatch, hOld; + + hPatch = CreateFileW(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) + { + hOld = CreateFileW(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + ret = TestApplyPatchToFileByHandles(hPatch, hOld, apply_flags); + CloseHandle(hOld); + } + CloseHandle(hPatch); + } + + return ret; }
5 years, 10 months
1
0
0
0
[reactos] 02/05: [MSPTCHA_APITEST] Initial tests. The filename intentionally does not contain the word 'patch', because this will trigger windows to auto-elevate the test app.
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fbe4a43f5db56023aaa61…
commit fbe4a43f5db56023aaa61a6e681ec611051f4f4d Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Sat Dec 1 22:35:29 2018 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Dec 15 16:28:59 2018 +0100 [MSPTCHA_APITEST] Initial tests. The filename intentionally does not contain the word 'patch', because this will trigger windows to auto-elevate the test app. --- modules/rostests/apitests/CMakeLists.txt | 1 + modules/rostests/apitests/mspatcha/CMakeLists.txt | 13 + modules/rostests/apitests/mspatcha/mspatcha.c | 519 ++++++++++++++++++++++ modules/rostests/apitests/mspatcha/testlist.c | 12 + 4 files changed, 545 insertions(+) diff --git a/modules/rostests/apitests/CMakeLists.txt b/modules/rostests/apitests/CMakeLists.txt index ec5048551e..8d4ee4834b 100644 --- a/modules/rostests/apitests/CMakeLists.txt +++ b/modules/rostests/apitests/CMakeLists.txt @@ -20,6 +20,7 @@ if(NOT ARCH STREQUAL "amd64") endif() add_subdirectory(localspl) add_subdirectory(msgina) +add_subdirectory(mspatcha) add_subdirectory(msvcrt) add_subdirectory(netapi32) add_subdirectory(netshell) diff --git a/modules/rostests/apitests/mspatcha/CMakeLists.txt b/modules/rostests/apitests/mspatcha/CMakeLists.txt new file mode 100644 index 0000000000..4f1398fbca --- /dev/null +++ b/modules/rostests/apitests/mspatcha/CMakeLists.txt @@ -0,0 +1,13 @@ + +list(APPEND SOURCE + mspatcha.c + testlist.c) + +# File name does not contain 'patch' on purpose! +# This triggers automatic elevation in Nt 6+ + +add_executable(msptcha_apitest ${SOURCE}) +set_module_type(msptcha_apitest win32cui) +add_importlibs(msptcha_apitest msvcrt kernel32 ntdll) +add_delay_importlibs(msptcha_apitest mspatcha) +add_rostests_file(TARGET msptcha_apitest) diff --git a/modules/rostests/apitests/mspatcha/mspatcha.c b/modules/rostests/apitests/mspatcha/mspatcha.c new file mode 100644 index 0000000000..1c01eedd77 --- /dev/null +++ b/modules/rostests/apitests/mspatcha/mspatcha.c @@ -0,0 +1,519 @@ +/* + * PROJECT: mspatcha_apitest + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: Tests for mspatcha + * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#define WIN32_NO_STATUS +#include <windows.h> + +#include "wine/test.h" +#include <patchapi.h> + + +/* Headers created with ExtractPatchHeaderToFileA */ +unsigned char in1_bin[8] = +{ + 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, /* testdata */ +}; +unsigned char out1_bin[26] = +{ + 0x74, 0x65, 0x73, 0x74, 0x20, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x57, 0x69, 0x74, 0x68, 0x20, /* test Data..With */ + 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, /* some extra */ +}; +unsigned char patch1_bin[75] = +{ + 0x50, 0x41, 0x31, 0x39, 0x01, 0x00, 0xc4, 0x00, 0x4e, 0x28, 0xb3, 0x5b, 0x9a, 0x08, 0xd1, 0x51, /* PA19....N(.[...Q */ + 0xf6, 0x01, 0xd2, 0x5e, 0x36, 0xe5, 0x99, 0x00, 0x00, 0x80, 0xac, 0x2a, 0x00, 0x00, 0x30, 0xa0, /* ...^6......*..0. */ + 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, /* .............tes */ + 0x74, 0x20, 0x44, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x57, 0x69, 0x74, 0x68, 0x20, 0x73, 0x6f, 0x6d, /* t Data..With som */ + 0x65, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0xa7, 0x19, 0x4a, 0x68, /* e extra..Jh */ +}; +unsigned char patch1_header_bin[31] = +{ + 0x50, 0x41, 0x31, 0x39, 0x01, 0x00, 0xc4, 0x00, 0x4e, 0x28, 0xb3, 0x5b, 0x9a, 0x08, 0xd1, 0x51, /* PA19....N(.[...Q */ + 0xf6, 0x01, 0xd2, 0x5e, 0x36, 0xe5, 0x99, 0x00, 0x00, 0x80, 0xac, 0xe9, 0xf0, 0x53, 0xf7, /* ...^6........S. */ +}; + +unsigned char in2_bin[25] = +{ + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xaa, /* ........"3DUfw.. */ + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, /* ......... */ +}; +unsigned char out2_bin[25] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xbb, /* ........"3DUfw.. */ + 0x00, 0xbb, 0x00, 0xbb, 0x00, 0xbb, 0x00, 0xbb, 0x00, /* ......... */ +}; +unsigned char patch2_bin[75] = +{ + 0x50, 0x41, 0x31, 0x39, 0x01, 0x00, 0xc4, 0x00, 0x62, 0x35, 0xb3, 0x5b, 0x99, 0xfa, 0xa0, 0x8a, /* PA19....b5.[.... */ + 0x02, 0x01, 0x80, 0x1d, 0xc2, 0x54, 0xfc, 0x00, 0x00, 0x80, 0xac, 0x2a, 0x00, 0x00, 0x30, 0x90, /* .....T.....*..0. */ + 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, /* ................ */ + 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xbb, 0x00, 0xbb, 0x00, /* ....."3DUfw..... */ + 0xbb, 0x00, 0xbb, 0x00, 0xbb, 0x00, 0x00, 0x14, 0x06, 0xeb, 0x61, /* ..........a */ +}; +unsigned char patch2_header_bin[31] = +{ + 0x50, 0x41, 0x31, 0x39, 0x01, 0x00, 0xc4, 0x00, 0x62, 0x35, 0xb3, 0x5b, 0x99, 0xfa, 0xa0, 0x8a, /* PA19....b5.[.... */ + 0x02, 0x01, 0x80, 0x1d, 0xc2, 0x54, 0xfc, 0x00, 0x00, 0x80, 0xac, 0xce, 0x5d, 0x8c, 0xed, /* .....T......].. */ +}; + +/* Minimum output size to trigger compression */ +unsigned char in3_bin[138] = +{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* .......... */ +}; +unsigned char out3_bin[152] = +{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ................ */ + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* ........ */ +}; +unsigned char patch3_bin[88] = +{ + 0x50, 0x41, 0x31, 0x39, 0x01, 0x00, 0xc4, 0x00, 0xb1, 0x57, 0xb3, 0x5b, 0x18, 0x81, 0xf9, 0xd8, /* PA19.....W.[.... */ + 0x1d, 0x41, 0x01, 0xce, 0xd9, 0x52, 0x0a, 0xf1, 0x00, 0x00, 0x80, 0xb8, 0x36, 0x00, 0x00, 0x10, /* .A...R......6... */ + 0x82, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x0f, 0x22, 0xff, 0xff, 0x35, 0xd8, /* ........ .."..5. */ + 0xfb, 0x8f, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x03, 0xb7, 0x08, 0xf7, 0x7d, /* ..........!....} */ + 0x7e, 0xdf, 0x40, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0d, 0x20, 0x7d, 0xbe, /* ~.@L......@.. }. */ + 0xf9, 0xbe, 0x68, 0xf4, 0x1f, 0x45, 0x3e, 0x35, /* ..h..E>5 */ +}; +unsigned char patch3_header_bin[32] = +{ + 0x50, 0x41, 0x31, 0x39, 0x01, 0x00, 0xc4, 0x00, 0xb1, 0x57, 0xb3, 0x5b, 0x18, 0x81, 0xf9, 0xd8, /* PA19.....W.[.... */ + 0x1d, 0x41, 0x01, 0xce, 0xd9, 0x52, 0x0a, 0xf1, 0x00, 0x00, 0x80, 0xb8, 0xbd, 0xeb, 0x70, 0xdd, /* .A...R........p. */ +}; + +typedef struct _bin_file +{ + unsigned char* data; + size_t len; +} bin_file; + +typedef struct _patch_data +{ + char* name; + bin_file input; + char* input_signature; + bin_file output; + char* output_signature; + bin_file patch; + bin_file patch_header; +} patch_data; + +#define MAKE_BIN(data_) { data_, sizeof(data_) } + +char temp_path[MAX_PATH]; + +BOOL extract2(char* filename, const unsigned char* data, size_t len) +{ + HANDLE hFile; + BOOL bRet; + DWORD dwWritten; + + if (!GetTempFileNameA(temp_path, "mpa", 0, filename)) + { + ok(0, "GetTempFileNameA failed %lu\n", GetLastError()); + return FALSE; + } + + hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + ok(0, "CreateFileA failed %lu\n", GetLastError()); + DeleteFileA(filename); + return FALSE; + } + + bRet = WriteFile(hFile, data, len, &dwWritten, NULL); + CloseHandle(hFile); + bRet = bRet && (dwWritten == len); + + if (!bRet) + { + ok(0, "WriteFile failed %lu\n", GetLastError()); + DeleteFileA(filename); + } + + return bRet; +} + +BOOL extract(char* filename, const bin_file* bin) +{ + return extract2(filename, bin->data, bin->len); +} + +HANDLE open_file(char* filename, BOOL bWrite) +{ + DWORD dwAccess = GENERIC_READ | (bWrite ? GENERIC_WRITE : 0); + DWORD dwAttr = (bWrite ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY); + return CreateFileA(filename, dwAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING, + dwAttr, NULL); +} + +void compare_file_(char* filename, const unsigned char* data, size_t len, const char* test_name, int line) +{ + char* buf; + size_t size; + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + ok_(__FILE__, line)(0, "Unable to open file %s(%lu), %s\n", filename, GetLastError(), test_name); + return; + } + size = GetFileSize(hFile, NULL); + ok(size == len, "Filesize is %u instead of %u, %s\n", size, len, test_name); + + buf = malloc(size); + if (buf) + { + DWORD dwRead; + if (ReadFile(hFile, buf, size, &dwRead, NULL) && dwRead == size) + { + ok(!memcmp(buf, data, min(size,len)), "Data mismatch, %s\n", test_name); + } + else + { + ok_(__FILE__, line)(0, "Unable to read %s(%lu), %s\n", filename, GetLastError(), test_name); + } + + free(buf); + } + else + { + ok_(__FILE__, line)(0, "Unable to allocate %u, %s\n", size, test_name); + } + + CloseHandle(hFile); +} + +#define compare_file(filename, data, len, test_name) compare_file_(filename, data, len, test_name, __LINE__) + +static void validate_signature(const char* casename, const char* fieldname, const bin_file* bin, const char* expected) +{ + char filename[MAX_PATH]; + WCHAR filenameW[MAX_PATH]; + HANDLE hFile; + unsigned char data[0x100]; + char signature[0x20] = {0}; + WCHAR signatureW[0x20] = {0}; + BOOL bResult; + + memset(signature, 0xaa, sizeof(signature)); + memcpy(data, bin->data, bin->len); + + if (!extract(filename, bin)) + return; + + memset(signature, 0xaa, sizeof(signature)-1); + bResult = GetFilePatchSignatureA(filename, 0, NULL, 0, NULL, 0, NULL, sizeof(signature), signature); + ok(bResult, "GetFilePatchSignatureA failed %lu, %s.%s\n", GetLastError(), casename, fieldname); + if (bResult) + { + // Signature is crc32 of data + ok(!_stricmp(expected, signature), "Got %s for %s.%s\n", signature, casename, fieldname); + } + + memset(signature, 0xaa, sizeof(signature)-1); + memset(signatureW, 0xaa, sizeof(signatureW)-sizeof(WCHAR)); + // Widechar version has a widechar signature + MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, _countof(filenameW)); + bResult = GetFilePatchSignatureW(filenameW, 0, NULL, 0, NULL, 0, NULL, sizeof(signatureW), signatureW); + ok(bResult, "GetFilePatchSignatureW failed %lu, %s.%s\n", GetLastError(), casename, fieldname); + if (bResult) + { + WideCharToMultiByte(CP_ACP, 0, signatureW, -1, signature, _countof(signature), NULL, NULL); + // Signature is crc32 of data + ok(!_stricmp(expected, signature), "Got %s for %s.%s\n", signature, casename, fieldname); + } + + memset(signature, 0xaa, sizeof(signature)-1); + // 'Handle' version has ansi signature + hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok(hFile != INVALID_HANDLE_VALUE, "Unable to open file %lu\n", GetLastError()); + if (hFile != INVALID_HANDLE_VALUE) + { + bResult = GetFilePatchSignatureByHandle(hFile, 0, NULL, 0, NULL, 0, NULL, sizeof(signature), signature); + ok(bResult, "GetFilePatchSignatureByHandle failed %lu, %s.%s\n", GetLastError(), casename, fieldname); + if (bResult) + { + // Signature is crc32 of data + ok(!_stricmp(expected, signature), "Got %s for %s.%s\n", signature, casename, fieldname); + } + + CloseHandle(hFile); + } + + DeleteFileA(filename); +} + +/* Copyright (C) 1986 Gary S. Brown + * Modified by Robert Shearman. You may use the following calc_crc32 code or + * tables extracted from it, as desired without restriction. */ +static const unsigned int crc_32_tab[] = +{ /* CRC polynomial 0xedb88320 */ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +unsigned int crc32(unsigned int seed, unsigned char* msg, unsigned int msglen) +{ + unsigned int rem = seed; + unsigned int i; + + for (i = 0; i < msglen; i++) + { + rem = crc_32_tab[(rem ^ msg[i]) & 0xff] ^ (rem >> 8); + } + + return rem; +} + +static void validate_patch(patch_data* current) +{ + UINT crc; + + crc = crc32(~0, current->patch.data, current->patch.len); + ok(crc == 0, "Invalid patch crc 0x%x for %s\n", crc, current->name); + + crc = crc32(~0, current->patch_header.data, current->patch_header.len); + ok(crc == 0, "Invalid patch_header crc 0x%x for %s\n", crc, current->name); +} + +static void apply_patch(patch_data* current) +{ + char patchname[MAX_PATH], targetname[MAX_PATH], outputname[MAX_PATH]; + BOOL bResult; + DWORD dwErr; + HANDLE hPatch, hTarget, hFind; + WIN32_FIND_DATAA wfd = { sizeof(wfd) }; + + if (!GetTempFileNameA(temp_path, "MPO", 0, outputname)) + { + ok(0, "GetTempFileNameA failed %lu, %s\n", GetLastError(), current->name); + return; + } + DeleteFileA(outputname); + + if (!extract(patchname, ¤t->patch)) + return; + if (!extract(targetname, ¤t->input)) + { + DeleteFileA(patchname); + return; + } + // There is a bug in 2k3, where calling 'TestApplyPatchToFileA' gives an AV... +#if 0 + bResult = TestApplyPatchToFileA(patchname, targetname, 0); +#else + hPatch = open_file(patchname, FALSE); + hTarget = open_file(targetname, FALSE); + bResult = TestApplyPatchToFileByHandles(hPatch, hTarget, 0); + CloseHandle(hPatch); + CloseHandle(hTarget); +#endif + ok(bResult, "TestApplyPatchToFileA failed %lu, %s\n", GetLastError(), current->name); + // Files are not touched + compare_file(patchname, current->patch.data, current->patch.len, current->name); + compare_file(targetname, current->input.data, current->input.len, current->name); + DeleteFileA(patchname); + DeleteFileA(targetname); + + + if (!extract2(patchname, current->patch.data, current->patch.len -1)) + return; + if (!extract(targetname, ¤t->input)) + { + DeleteFileA(patchname); + return; + } + hPatch = open_file(patchname, FALSE); + hTarget = open_file(targetname, FALSE); + bResult = TestApplyPatchToFileByHandles(hPatch, hTarget, 0); + dwErr = GetLastError(); + CloseHandle(hPatch); + CloseHandle(hTarget); + ok(!bResult, "TestApplyPatchToFileA succeeded, %s\n", current->name); + ok(dwErr == ERROR_PATCH_CORRUPT, "TestApplyPatchToFileA GetLastError %lx, %s\n", dwErr, current->name); + // Files are not touched + compare_file(patchname, current->patch.data, current->patch.len - 1, current->name); + compare_file(targetname, current->input.data, current->input.len, current->name); + DeleteFileA(patchname); + DeleteFileA(targetname); + + if (!extract(patchname, ¤t->patch)) + return; + if (!extract2(targetname, current->input.data, current->input.len -1)) + { + DeleteFileA(patchname); + return; + } + hPatch = open_file(patchname, FALSE); + hTarget = open_file(targetname, FALSE); + bResult = TestApplyPatchToFileByHandles(hPatch, hTarget, 0); + dwErr = GetLastError(); + CloseHandle(hPatch); + CloseHandle(hTarget); + ok(!bResult, "TestApplyPatchToFileA succeeded, %s\n", current->name); + ok(dwErr == ERROR_PATCH_WRONG_FILE, "TestApplyPatchToFileA GetLastError %lx, %s\n", dwErr, current->name); + // Files are not touched + compare_file(patchname, current->patch.data, current->patch.len, current->name); + compare_file(targetname, current->input.data, current->input.len -1, current->name); + DeleteFileA(patchname); + DeleteFileA(targetname); + + if (!extract(patchname, ¤t->patch)) + return; + if (!extract(targetname, ¤t->input)) + { + DeleteFileA(patchname); + return; + } + bResult = ApplyPatchToFileA(patchname, targetname, outputname, APPLY_OPTION_TEST_ONLY); + + ok(bResult, "ApplyPatchToFileA failed %lu, %s\n", GetLastError(), current->name); + // Files are not touched + compare_file(patchname, current->patch.data, current->patch.len, current->name); + compare_file(targetname, current->input.data, current->input.len, current->name); + // W2k3 creates an empty file, W10 does not create a file + hFind = FindFirstFileA(outputname, &wfd); + ok(hFind == INVALID_HANDLE_VALUE || wfd.nFileSizeLow == 0, "Got a (non-empty) file, %s\n", current->name); + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); + DeleteFileA(patchname); + DeleteFileA(targetname); + DeleteFileA(outputname); + + if (!extract(patchname, ¤t->patch)) + return; + if (!extract(targetname, ¤t->input)) + { + DeleteFileA(patchname); + return; + } + bResult = ApplyPatchToFileA(patchname, targetname, outputname, 0); + ok(bResult, "ApplyPatchToFileA failed %lu, %s\n", GetLastError(), current->name); + // Files are not touched + compare_file(patchname, current->patch.data, current->patch.len, current->name); + compare_file(targetname, current->input.data, current->input.len, current->name); + // One output file + compare_file(outputname, current->output.data, current->output.len, current->name); + DeleteFileA(patchname); + DeleteFileA(targetname); + DeleteFileA(outputname); +} + + +void test_one(patch_data* current) +{ + validate_signature(current->name, "input", ¤t->input, current->input_signature); + validate_signature(current->name, "output", ¤t->output, current->output_signature); + apply_patch(current); + validate_patch(current); +} + + + +static patch_data data[] = +{ + { + "in1_text", + MAKE_BIN(in1_bin), + "99e5365e", + MAKE_BIN(out1_bin), + "f651d108", + MAKE_BIN(patch1_bin), + MAKE_BIN(patch1_header_bin), + }, + { + "in2_binary", + MAKE_BIN(in2_bin), + "fc54c21d", + MAKE_BIN(out2_bin), + "028aa0fa", + MAKE_BIN(patch2_bin), + MAKE_BIN(patch2_header_bin), + }, + { + "in3_compression", + MAKE_BIN(in3_bin), + "f10a52d9", + MAKE_BIN(out3_bin), + "411dd8f9", + MAKE_BIN(patch3_bin), + MAKE_BIN(patch3_header_bin), + }, +}; + + +START_TEST(mspatcha) +{ + size_t n; + + GetTempPathA(_countof(temp_path), temp_path); + + for (n = 0; n < _countof(data); ++n) + { + test_one(data + n); + } +} diff --git a/modules/rostests/apitests/mspatcha/testlist.c b/modules/rostests/apitests/mspatcha/testlist.c new file mode 100644 index 0000000000..a8bf1521bd --- /dev/null +++ b/modules/rostests/apitests/mspatcha/testlist.c @@ -0,0 +1,12 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define STANDALONE +#include <wine/test.h> + +extern void func_mspatcha(void); + +const struct test winetest_testlist[] = +{ + { "mspatcha", func_mspatcha }, + { 0, 0 } +};
5 years, 10 months
1
0
0
0
← Newer
1
...
17
18
19
20
21
22
23
...
33
Older →
Jump to page:
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
26
27
28
29
30
31
32
33
Results per page:
10
25
50
100
200