ข้ามไปที่เนื้อหาหลัก
การสนับสนุน
ลงชื่อเข้าใช้
ลงชื่อเข้าใช้ด้วย Microsoft
ลงชื่อเข้าใช้หรือสร้างบัญชี
สวัสดี
เลือกบัญชีอื่น
คุณมีหลายบัญชี
เลือกบัญชีที่คุณต้องการลงชื่อเข้าใช้

บทนำ

เมื่ออุปกรณ์เก็บข้อมูลถูกเชื่อมต่อกับ Windows แม้เพียงสั้น ๆ windows สร้างข้อมูลรีจิสทรีสำหรับอุปกรณ์ ช่วงเวลา รีจิสทรีอาจประกอบด้วยรายการจำนวนมากสำหรับอุปกรณ์ที่จะไม่ใช้อีกต่อไป บทความนี้อธิบายวิธีการเอาข้อมูลนี้ออกจากรีจิสทรีของระบบ

เป็นความรับผิดชอบของซอฟต์แวร์ที่สร้างการเชื่อมต่อระหว่างอุปกรณ์เก็บข้อมูลและ Windows เมื่อต้องการล้างข้อมูลของอุปกรณ์ได้อย่างถูกต้อง กระบวนการนี้เป็นสิ่งจำเป็นเนื่องจาก Windows ไม่ทราบเมื่ออุปกรณ์เก็บข้อมูลจะถูกลบอย่างถาวร หรือชั่วคราว แต่ทราบจากซอฟต์แวร์ที่สร้างการเชื่อมต่อโดยทั่วไปนี้ ตัวอย่างเช่น ถ้าซอฟต์แวร์การสำรองข้อมูลถูกกำหนดหมายเลขหน่วยทางลอจิคัล (Lun) สำหรับวัตถุประสงค์ในการสำรองข้อมูล และ unmounting Lun แล้ว จะความรับผิดชอบของซอฟต์แวร์การสำรองข้อมูลเพื่อล้างข้อมูลพร้อมจาก Windows เนื่องจากอุปกรณ์เก็บข้อมูลเดียวกันจะไม่มีอีกต่อไป สามารถใช้อีกครั้ง Windows

ข้อมูลเพิ่มเติม

เมื่ออุปกรณ์ใหม่ถูกเชื่อมต่อกับคอมพิวเตอร์ Windows จะบันทึกข้อมูลที่เกี่ยวกับอุปกรณ์ในรีจิสทรีของระบบ สำหรับอุปกรณ์ส่วนใหญ่ ขั้นตอนนี้ไม่ก่อให้เกิดปัญหา อย่างไรก็ตาม หลังจากอุปกรณ์เก็บข้อมูลแบบมีการนำเสนอ โดย ผ่านช่องสัญญาณ fiber หรือ iSCSI บหยุด อุปกรณ์อาจไม่สามารถพบอีกครั้งจากคอมพิวเตอร์ ตัวอย่างเช่น คุณอาจสามารถระบุอุปกรณ์ที่ ตามหมายเลขลำดับประจำสินค้า หรือ ตามเพ SCSI 0x80 และ 0x83

ในสถานการณ์นี้ รีจิสทรีอาจประกอบด้วยรายการสำหรับอุปกรณ์ที่อาจไม่ปรากฏอีกต่อไป ไม่เพียงทำรายการเหล่านี้ใช้พื้นที่ว่างในรีจิสทรี รายการเหล่านี้อาจทำให้ปัญหาในการดำเนินงานในที่สุด ตัวอย่างเช่น เนื่องจากดัชนีสำหรับฟังก์ชันการทำงานแบบพลักแอนด์เพลย์ใช้ค่าทศนิยมสี่ตำแหน่ง ปัญหาอาจเกิดขึ้นเมื่อมีการเชื่อมต่ออุปกรณ์ 10,001

เมื่อต้องการแก้ไขข้อจำกัดนี้ในฟังก์ชันการทำงานแบบพลักแอนด์เพลย์ คุณอาจต้องการเอาข้อมูลเกี่ยวกับอุปกรณ์จากรีจิสทรีเมื่ออุปกรณ์อยู่ในฮาร์ดดิสก์ที่ไม่มีอยู่ คุณสามารถทำเช่นนี้ได้ โดยใช้โปรแกรมอรรถประโยชน์นี้Microsoft DevNodeClean

วิธีการสร้างสำหรับ Windows Server 2003, Windows Server 2008, Windows Server 2008 R2 และ Visual Studio 2005

การล้างข้อมูลรีจิสทรีสำหรับคลาส GUID_DEVCLASS_DISKDRIVE ดิสก์ GUID สำหรับ GUID_DEVCLASS_VOLUME ดิสก์คลาส GUID ให้ทำตามขั้นตอนเหล่านี้

หมายเหตุ  เราขอแนะนำให้ คุณใช้โปรแกรมอรรถประโยชน์การDevNodeCleanสำหรับงานนี้ ขั้นตอนต่อไปนี้และตัวอย่างรหัสในขั้นตอนที่ 7 ให้มาสำหรับวัตถุประสงค์ในการให้ข้อมูลเท่านั้น

  1. เรียกใช้ฟังก์ชันSetupDiGetClassDevsเพื่อขอรับข้อมูลสำหรับคลาสที่เกี่ยวข้องกับ GUID

  2. เรียกใช้ฟังก์ชันSetupDiEnumDeviceInfoเพื่อขอรับข้อมูลของอินสแตนซ์สำหรับอุปกรณ์แต่ละชนิดในชั้นปัจจุบัน

  3. เรียกใช้ฟังก์ชันCM_Get_DevNode_Statusเพื่อดูว่า ข้อมูลของอุปกรณ์ปัจจุบันแทนอุปกรณ์การขาดงาน ตรวจสอบว่า สถานะฟังก์ชัน CR_NO_SUCH_DEVINST หรือ CR_NO_SUCH_VALUE เท่านั้น

  4. อีกทางหนึ่งคือ สำหรับอุปกรณ์การขาดงาน เรียกฟังก์ชันCM_Get_Device_IDเพื่อขอรับ ID อินสแตนซ์อุปกรณ์ และแสดงรหัสก่อนที่จะลบข้อมูล

  5. สำหรับอุปกรณ์ขาดงาน ใช้คลาสข้อมูลที่คุณได้รับในขั้นตอนที่ 1 และข้อมูลอินสแตนซ์ที่คุณได้รับในขั้นตอนที่ 2 เรียกใช้ฟังก์ชันSetupDiCallClassInstaller (DIF_REMOVE,...)เมื่อต้องการเอาข้อมูลออกจากรีจิสทรี

  6. เมื่อได้รับการจัดการอุปกรณ์ทั้งหมดในชั้นปัจจุบัน เรียกฟังก์ชันSetupDiDestroyDeviceInfoListเพื่อล้าง

หมายเหตุ ในบางสถานการณ์ คุณอาจจะต้องทำความสะอาดรีจิสทรีไม่ใช่เฉพาะสำหรับ GUID_DEVCLASS_DISKDRIVE และ GUID_DEVCLASS_VOLUME ดิสก์คลาส guid ของ แต่ยังสำหรับ GUID_DEVCLASS_SCSIADAPTER และ GUID_DEVCLASS_VOLUMESNAPSHOT คลาส Guid ของดิสก์ เมื่อต้องการทำเช่นนี้ คุณต้องเปลี่ยนคำนิยามDiskClassesToCleanในตัวอย่างรหัสต่อไปนี้

แอพลิเคชันคอนโซล Win32 ต่อไปนี้คือ ตัวอย่างของโปรแกรมประยุกต์ที่ล้างรีจิสทรี เมื่อต้องการใช้โปรแกรมประยุกต์นี้ ให้ทำตามขั้นตอนเหล่านี้

Microsoft ให้ตัวอย่างการเขียนโปรแกรมไว้สำหรับประกอบการอธิบายเท่านั้นโดยไม่มีการรับประกันไม่ว่าจะโดยชัดแจ้งหรือโดยนัย กรณีนี้รวมถึงแต่มิได้จำกัดเพียงแค่การการรับประกันโดยนัยเกี่ยวกับการจำหน่ายเป็นสินค้าหรือความเหมาะสำหรับวัตถุประสงค์เฉพาะ บทความนี้ตั้งสมมติฐานว่าคุณมีความคุ้นเคยกับภาษาการเขียนโปรแกรมที่กำลังแสดงและคุ้นเคยกับเครื่องมือที่ใช้ใน การสร้างและแก้จุดบกพร่องของขั้นตอนการดำเนินการ วิศวกรฝ่ายสนับสนุนของ Microsoft สามารถช่วยอธิบายเกี่ยวกับหน้าที่การใช้งานของกระบวนการเฉพาะ อย่างไรก็ตาม จะไม่แก้ไขตัวอย่างเหล่านี้เพื่อเพิ่มฟังก์ชัน หรือสร้างขั้นตอนเพื่อตอบสนองความต้องการเฉพาะของคุณ

  1. ใน Microsoft Visual Studio 2005 คลิกสร้างบนเมนูแฟ้มแล้ว คลิ กโครงการ

  2. ขยายVisual C++และจากนั้น คลิกWin32

  3. คลิกแอพลิเคชันคอนโซล Win32พิมพ์การล้างข้อมูลในกล่องข้อความชื่อและจากนั้น คลิกตกลง

  4. คลิกเสร็จสิ้นในกล่องโต้ตอบตัวช่วยสร้างโปรแกรมประยุกต์ Win32

  5. ในโซลูชัน Explorer ขยายแฟ้มแหล่งที่มาCleanup.cppคลิกขวา ความแสดงโค้ด

  6. ค้นหาตำแหน่งของรหัสต่อไปนี้:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. แทนรหัสที่คุณพบในขั้นตอนที่ 6 กับรหัสต่อไปนี้

    /**************************************************************************************************/     
    /*                                                                                                */     
    /* Copyright (c) 2007 Microsoft Corporation.  All Rights Reserved                                 */     
    /*                                                                                                */     
    /**************************************************************************************************/     
    
    #pragma warning( disable : 4201 ) // nonstandard extension used : nameless strut/union
    
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <stddef.h>
    #include <tchar.h>
    #include <setupapi.h>
    #include <cfgmgr32.h>
    #include <initguid.h>
    #include <devguid.h>
    
    #define SIZECHARS(x) (sizeof((x))/sizeof(TCHAR))
    #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
    
    CONST GUID *DiskClassesToClean[2] = {
        &GUID_DEVCLASS_DISKDRIVE,
        &GUID_DEVCLASS_VOLUME
    };
    
    /**************************************************************************************************/
    /*                                                                                                */
    /* The user must be member of Administrator group and must have backup and restore permissions         */
    /* (SE_BACKUP_NAME and SE_RESTORE_NAME). No check for these is performed in this example.              */
    /*                                                                                                */
    /**************************************************************************************************/
    int
    __cdecl
    main(
         IN int    ArgC,
         IN char * pArgV[]
        )
    {
        HDEVINFO DeviceInfoSet;
        SP_DEVINFO_DATA DeviceInfoData;
        ULONG DevicesRemoved = 0,
              i,
              MemberIndex,
              Status, 
              Problem,
              ulClassesToCleanIdx;
        BOOL bDoRemove = TRUE;
        CONFIGRET cr;
        TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
        OSVERSIONINFO osvi;
        const GUID ** ClassesToClean;
    
        //
        // Parse parameters.
        //
        for (i = 1; i < (ULONG)ArgC; i++) {
            //
            // Check for help.
            //
            if ( (lstrcmpi(pArgV[i], TEXT("-?")) == 0) ||
                    (lstrcmpi(pArgV[i], TEXT("/?")) == 0) ){
    
                printf("\nCleanUp will remove phantom storage device nodes from this machine.\n\n");
                printf("Usage:  CleanUp \n");
                printf("\twhere /n displays but does not remove the phantom devnodes.\n");
                printf("\nBackup and Restore privileges are required to run this utility.\n");
                return 0;
            }
    
            //
            // Check for -n, which means just list the devices that we would remove.
            //
            if ( (lstrcmpi(pArgV[i], TEXT("-n")) == 0) ||
                 (lstrcmpi(pArgV[i], TEXT("/n")) == 0) ) {
                bDoRemove = FALSE;
            }
        }
    
        //
        // Run only on Windows XP/2003 (version 5.1) or later.
        //
    
        ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    
        if (!GetVersionEx(&osvi)) {
            printf("CleanUp:  Unable to verify Windows version, exiting...\n");
            return -1;
        }
    
        if ((osvi.dwMajorVersion == 5) &&
            ((osvi.dwMinorVersion == 1) || (osvi.dwMinorVersion == 2))) {
        }
        else if (osvi.dwMajorVersion>=6) {
        }
        else
        {
            printf("CleanUp:  This utility is  designed to run on Windows XP/2003 and later\n");
            return -1;
        }
    
        ClassesToClean = DiskClassesToClean;
        ulClassesToCleanIdx = arraysize(DiskClassesToClean);
    
        for (i=0; (i<ulClassesToCleanIdx) && (bDoRemove); i++) {
    
            DeviceInfoSet = SetupDiGetClassDevs(ClassesToClean[i],
                                                NULL,
                                                NULL,
                                                0
                                                );
    
            if (INVALID_HANDLE_VALUE!=DeviceInfoSet) {
    
                DeviceInfoData.cbSize = sizeof(DeviceInfoData);
                MemberIndex = 0;
    
                while (SetupDiEnumDeviceInfo(DeviceInfoSet,
                                             MemberIndex++,
                                             &DeviceInfoData
                                             )) {
    
                    //
                    // Determine whether this device is a phantom.
                    //
                    cr = CM_Get_DevNode_Status(&Status,
                                               &Problem,
                                               DeviceInfoData.DevInst,
                                               0
                                               );
    
                    if ((cr == CR_NO_SUCH_DEVINST) ||
                        (cr == CR_NO_SUCH_VALUE)) {
                        //
                        // This is a phantom. Now get the DeviceInstanceId so we
                        // can display this as output, then delete the phantom if requested.
                        //
                        if (CM_Get_Device_ID(DeviceInfoData.DevInst,
                                             DeviceInstanceId,
                                             SIZECHARS(DeviceInstanceId),
                                             0) == CR_SUCCESS) {
    
                            if (bDoRemove) {
                                printf("DevNodePhantomCleaner:  %s will be removed.\n",
                                       DeviceInstanceId);
    
                                //
                                // Call DIF_REMOVE to remove the device's hardware
                                // and software registry keys.
                                //
                                if (SetupDiCallClassInstaller(DIF_REMOVE,
                                                              DeviceInfoSet,
                                                              &DeviceInfoData
                                                              )) {
                                    DevicesRemoved++;
                                } else {
                                    printf("CleanUp:  Error 0x%X removing phantom\n",
                                           GetLastError);
                                }
                            } else {
                                printf("CleanUp:  %s would have been removed.\n",
                                       DeviceInstanceId);
                            }
                        }
                    }
                }
    
                SetupDiDestroyDeviceInfoList(DeviceInfoSet);
            }
        }
    
        return DevicesRemoved;
    }
  8. คลิกเมนูตรวจแก้จุดบกพร่องและจากนั้น คลิกเริ่มต้นการดีบัก

วิธีการสร้างสำหรับ Windows Server 2012 และ 2012 Studio แสดงผล

เมื่อต้องสร้างสำหรับ Windows Server 2012 และ Microsoft Visual Studio 2012 ให้ทำตามขั้นตอนเหล่านี้

หมายเหตุ  เราขอแนะนำให้ คุณใช้โปรแกรมอรรถประโยชน์การDevNodeCleanสำหรับงานนี้ ขั้นตอนต่อไปนี้และตัวอย่างรหัสในขั้นตอนที่ 7 ให้มาสำหรับวัตถุประสงค์ในการให้ข้อมูลเท่านั้น

  1. ใน Microsoft Visual Studio 2012 คลิกสร้างบนเมนูแฟ้มแล้ว คลิ กโครงการ

  2. ในกล่องโต้ตอบโครงการใหม่พิมพ์ล้างข้อมูลลงในฟิลด์ชื่อและจากนั้น คลิกสองครั้งที่โครงการ Win32

  3. ในวิซาร์โปรแกรมประยุกต์ Win32 คลิกถัดไป

  4. ภายใต้ชนิดของแอพลิเคชันคลิกเพื่อเลือกโปรแกรมประยุกต์คอนโซลและจากนั้น คลิกเสร็จสิ้น

  5. ในโซลูชัน Explorer ขยายแฟ้มแหล่งที่มาCleanup.cppคลิกขวา ความแสดงโค้ด

  6. ค้นหาตำแหน่งของรหัสต่อไปนี้:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. แทนรหัสที่คุณพบในขั้นตอนที่ 6 กับรหัสต่อไปนี้

    //DevPhantomClnr.cpp : Defines the entry point for the console application.
    // 
     
    #include "stdafx.h"
    
    /**************************************************************************************************/     
    /*                                                                                                */     
    /* Copyright (c) 2007 Microsoft Corporation.  All Rights Reserved                                 */     
    /*                                                                                                */     
    /**************************************************************************************************/     
    
    #pragma warning( disable : 4201 ) // nonstandard extension used : nameless strut/union
    
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <stddef.h>
    #include <tchar.h>
    #include <setupapi.h>
    #include <cfgmgr32.h>
    #include <initguid.h>
    #include <devguid.h>
    
    #define SIZECHARS(x) (sizeof((x))/sizeof(TCHAR))
    #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
    
    CONST GUID *DiskClassesToClean[2] = {
        &GUID_DEVCLASS_DISKDRIVE,
        &GUID_DEVCLASS_VOLUME
    };
    
    /**************************************************************************************************/
    /*                                                                                                */
    /* The user must be member of Administrator group and must have backup and restore permissions         */
    /* (SE_BACKUP_NAME and SE_RESTORE_NAME). No check for these is performed in this example.              */
    /*                                                                                                */
    /**************************************************************************************************/
    int
    __cdecl
    main(
         IN int    ArgC,
         IN LPCWSTR pArgV[]
        )
    {
        HDEVINFO DeviceInfoSet;
        SP_DEVINFO_DATA DeviceInfoData;
        ULONG DevicesRemoved = 0,
              i,
              MemberIndex,
              Status, 
              Problem,
              ulClassesToCleanIdx;
        BOOL bDoRemove = TRUE;
        CONFIGRET cr;
        TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
        OSVERSIONINFO osvi;
        const GUID ** ClassesToClean;
    
        //
        // Parse parameters.
        //
        for (i = 1; i < (ULONG)ArgC; i++) {
            //
            // Check for help.
            //
            if ( (lstrcmpi(pArgV[i], L"-?") == 0) ||
                    (lstrcmpi(pArgV[i], L"/?") == 0) ){
    
                printf("\nDevNodePhantomCleaner will remove phantom storage device nodes from this machine.\n\n");
                printf("Usage:  nDevNodePhantomCleaner \n");
                printf("\tWhere /n displays but does not remove the phantom devnodes.\n");
                printf("\nBackup and Restore privileges are required to run this utility.\n");
                return 0;
            }
    
            //
            // Check for -n, which means just list the devices that we would remove.
            //
            if ( (lstrcmpi(pArgV[i], L"-n") == 0) ||
                 (lstrcmpi(pArgV[i], L"/n") == 0) ) {
                bDoRemove = FALSE;
            }
        }
    
        //
        // Run only on Windows XP/2003 (version 5.1) or later.
        //
    
        ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    
        if (!GetVersionEx(&osvi)) {
            printf("DevNodePhantomCleaner:  Unable to verify Windows version, exiting...\n");
            return -1;
        }
    
        if ((osvi.dwMajorVersion == 5) &&
            ((osvi.dwMinorVersion == 1) || (osvi.dwMinorVersion == 2))) {
        
        // 5.1 || 5.2
    
        }
    
        else if (osvi.dwMajorVersion>=6) {
        
        //Nothing special on 6.x
    
        }
    
        else
        {
            printf("DevNodePhantomCleaner:  This utility is  designed to run on Windows XP/2003 and later\n");
            return -1;
        }
    
        ClassesToClean = DiskClassesToClean;
        ulClassesToCleanIdx = arraysize(DiskClassesToClean);
    
        for (i=0; (i<ulClassesToCleanIdx) && (bDoRemove); i++) {
    
            DeviceInfoSet = SetupDiGetClassDevs(ClassesToClean[i],
                                                NULL,
                                                NULL,
                                                0
                                                );
    
            if (INVALID_HANDLE_VALUE!=DeviceInfoSet) {
    
                DeviceInfoData.cbSize = sizeof(DeviceInfoData);
                MemberIndex = 0;
    
                while (SetupDiEnumDeviceInfo(DeviceInfoSet,
                                             MemberIndex++,
                                             &DeviceInfoData
                                             )) {
    
                    //
                    // Determine whether this device is a phantom.
                    //
                    cr = CM_Get_DevNode_Status(&Status,
                                               &Problem,
                                               DeviceInfoData.DevInst,
                                               0
                                               );
    
                    if ((cr == CR_NO_SUCH_DEVINST) ||
                        (cr == CR_NO_SUCH_VALUE)) {
                        //
                        // This is a phantom. Now get the DeviceInstanceId so we
                        // can display this as output, then delete the phantom if requested.
                        //
                        if (CM_Get_Device_ID(DeviceInfoData.DevInst,
                                             DeviceInstanceId,
                                             SIZECHARS(DeviceInstanceId),
                                             0) == CR_SUCCESS) {
    
                            if (bDoRemove) {
                                printf("DevNodePhantomCleaner:  %ws will be removed.\n",
                                       DeviceInstanceId);
    
                                //
                                // Call DIF_REMOVE to remove the device's hardware
                                // and software registry keys.
                                //
                                if (SetupDiCallClassInstaller(DIF_REMOVE,
                                                              DeviceInfoSet,
                                                              &DeviceInfoData
                                                              )) {
                                    DevicesRemoved++;
                                } else {
                                    printf("DevNodePhantomCleaner:  Error 0x%x removing phantom\n",
                                           GetLastError());
                                }
                            } else {
                                printf("DevNodePhantomCleaner:  %ws would have been removed.\n",
                                       DeviceInstanceId);
                            }
                        }
                    }
                }
    
                SetupDiDestroyDeviceInfoList(DeviceInfoSet);
            }
        }
    
        return DevicesRemoved;
    }
  8. ในโซลูชัน Explorerล้างข้อมูลบนคลิกขวา แล้ว คลิ กคุณสมบัติ

  9. ขยายคุณสมบัติการตั้งค่าคอนฟิกขยายตัวเชื่อมโยงข้อมูลและจากนั้น คลิกป้อนเข้า

  10. เลือกการอ้างอิงเพิ่มเติมคลิกลูกศรลง จากนั้นแก้ไข

  11. ในกล่องโต้ตอบการอ้างอิงเพิ่มเติมชนิดsetupapi.libและcfgmgr32.lib

  12. คลิก ตกลง สองครั้ง

  13. สร้างโครงการ

ต้องการความช่วยเหลือเพิ่มเติมหรือไม่

ต้องการตัวเลือกเพิ่มเติมหรือไม่

สํารวจสิทธิประโยชน์ของการสมัครใช้งาน เรียกดูหลักสูตรการฝึกอบรม เรียนรู้วิธีการรักษาความปลอดภัยอุปกรณ์ของคุณ และอื่นๆ

ชุมชนช่วยให้คุณถามและตอบคําถาม ให้คําติชม และรับฟังจากผู้เชี่ยวชาญที่มีความรู้มากมาย

ข้อมูลนี้เป็นประโยชน์หรือไม่

คุณพึงพอใจกับคุณภาพภาษาเพียงใด
สิ่งที่ส่งผลต่อประสบการณ์ใช้งานของคุณ
เมื่อกดส่ง คำติชมของคุณจะถูกใช้เพื่อปรับปรุงผลิตภัณฑ์และบริการของ Microsoft ผู้ดูแลระบบ IT ของคุณจะสามารถรวบรวมข้อมูลนี้ได้ นโยบายความเป็นส่วนตัว

ขอบคุณสำหรับคำติชมของคุณ!

×