1

The functions PathMatchSpec() and PathMatchSpecEx() return incorrect results for the Korean language.

In the test program below, the name is "수납파일" and the mask is "수납*".

If the Windows language is e.g. English or German - it works fine.

If the Windows language is Korean, both functions return incorrect results.

How should I use the functions to make them work properly in all languages?

I don't know the Korean language. Tested on Windows 10 and 11 with Delphi 10.4.2.

C++ console:

#include <iostream>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
int main()
{
    if (PathMatchSpec(L"수납파일", L"수납*"))
       std::cout << "PathMatchSpec success!\n";
    else
        std::cout << "PathMatchSpec failed!\n";

    if (PathMatchSpecEx(L"수납파일", L"수납*", PMSF_NORMAL)==S_OK)
        std::cout << "PathMatchSpecEx success!\n";
    else
        std::cout << "PathMatchSpecEx failed!\n";
}

Test program:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,Winapi.ShLwApi,
  System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    Label3: TLabel;
    Button2: TButton;
    Label4: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;    

  function PathMatchSpecEx(pszFile, pszSpec: LPCWSTR; dwFlags: DWORD ): HRESULT; stdcall;
  {$EXTERNALSYM PathMatchSpecEx}
var
  Form1: TForm1;

implementation

{$R *.dfm}


function PathMatchSpecEx; external 'shlwapi.dll' name 'PathMatchSpecExW';    


procedure TForm1.FormCreate(Sender: TObject);
var fileName, fileMask: string;
begin
  fileName := '수납파일';
  fileMask:= '수납*';

  Edit1.Text := fileName;
  Edit2.Text := fileMask;   

end;   


procedure TForm1.Button1Click(Sender: TObject);
var fileName, fileMask: string;
begin
  fileName := Edit1.Text;
  fileMask := Edit2.Text;

  if PathMatchSpecEx(PChar(fileName), PChar(fileMask),0)=S_OK then
     Label3.Caption := 'Success!'
  else
     Label3.Caption := 'PathMatchSpecEx failed!';
end;

procedure TForm1.Button2Click(Sender: TObject);
var fileName, fileMask: string;
begin
  fileName := Edit1.Text;
  fileMask := Edit2.Text;

  if PathMatchSpec(PChar(fileName), PChar(fileMask)) then
     Label4.Caption := 'Success!'
  else
     Label4.Caption := 'PathMatchSpec failed!';
end;

end.
Eric
  • 21
  • 3
  • Cannot reproduce with `PathMatchSpecEx(L"수납파일",L"수납*", PMSF_NORMAL);` when Windows language is Korean. – YangXiaoPo-MSFT Feb 13 '23 at 06:26
  • Why `String` but then `PWideChar`? Shouldn't it be consistently as per your Delphi version `PChar`? You don't need to know [Hangul](https://en.wikipedia.org/wiki/Hangul) - just enter the same graphemes, just like `グリーン` and `グリ*`, or `ਹਾਂਗਗੁਲ` and `ਹਾਂਗ*`. – AmigoJack Feb 13 '23 at 08:14
  • @YangXiaoPo-MSFT Is your Windows installation language Korean? My Windows installation language is German. If I start the test program with German or English Windows language, it works perfectly. I added Korean language to my windows. After switching Windows to Korean, the PathMatchSpec and PathMatchSpecEx functions fail. – Eric Feb 13 '23 at 10:19
  • PWideChar changed to PChar in the test program - this has no relevance to the problem, the result with delphi 10.4.2 is same. – Eric Feb 13 '23 at 10:26
  • @Eric My Windows, which is Windows 11 Enterprise(22H2,22621.1105), installation language is English. Can you reproduce using a c++ console application? You may open an incident via 'Contact us' tab at link below so that our engineer can work with you closely: https://developer.microsoft.com/en-us/windows/support/ and please choose the 'Technical Support - Coding/Debugging' for Windows SDK for this issue. In-addition, if the support engineer determines that the issue is the result of a bug the service request will be a no-charge case and you won't be charged. – YangXiaoPo-MSFT Feb 14 '23 at 02:17
  • Thanks for your comment. I rechecked everything on my end, removing and reinstalling any additional Windows languages. Now when I switch to Korean, both functions work correctly. So I think something must have been wrong with the first language installation. – Eric Feb 14 '23 at 20:52
  • Unfortunately the problem is not solved. I received additional important information from the user who reported the problem. The problem always occurs when the Windows language for non Unicode programs (system locale) is Korean. The user has Windows display language Korean and Windows system locale language Korean and then this doesn't work. I have also tested it with the C++ test program (added above in the description) and get the same problem. So the question remains - what is wrong? – Eric Feb 15 '23 at 20:33

1 Answers1

1

The code page of the source file makes a difference as you said in comments. The following code explains what happened.

#include<windows.h>
#include <iostream>
#include <wchar.h>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

PCHAR convert(PTCHAR p)
{
    int size = WideCharToMultiByte(50225, 0, p, -1, NULL, 0, NULL, NULL);
    PCHAR c = (PCHAR)malloc(size);
    int error = WideCharToMultiByte(50225, 0, p, -1, c, size, NULL, NULL);
    if (error == 0)
    {
        DWORD d = GetLastError();
    }
    return c;
}

int main()
{
    TCHAR a[] = L"수납파일";
    TCHAR b[] = L"수납*";

    PCHAR c = convert(a);
    PCHAR d = convert(b);
    //d[9] = '\x2a';
    //d[10] = '\x0';
    if (PathMatchSpec(a, b))
        std::cout << "PathMatchSpec success!\n";
    else
        std::cout << "PathMatchSpec failed!\n";

    if (PathMatchSpecEx(a, b, PMSF_NORMAL) == S_OK)
        std::cout << "PathMatchSpecEx success!\n";
    else
        std::cout << "PathMatchSpecEx failed!\n";

    if (PathMatchSpecA(c, d))
        std::cout << "PathMatchSpec success!\n";
    else
        std::cout << "PathMatchSpec failed!\n";

    if (PathMatchSpecExA(c, d, PMSF_NORMAL) == S_OK)
        std::cout << "PathMatchSpecEx success!\n";
    else
        std::cout << "PathMatchSpecEx failed!\n";
}


Save the source file in code page 50225.
overall overall
aa
bb


Save the source file in Unicode code page 65001.
overalloverall
aa
bb
cc
dd\

YangXiaoPo-MSFT
  • 1,589
  • 1
  • 4
  • 22
  • Thanks for your example. It works fine. I tried to write the example in Delphi, but I can't. Maybe there is someone else who can help. – Eric Feb 18 '23 at 16:11
  • In VisualStudio, I use what [the answer](https://stackoverflow.com/a/75374888/15511041) showed to change saving encoding. You need to save your source files in Unicode. – YangXiaoPo-MSFT Feb 21 '23 at 05:20